Глава 12 Расширения языка
13 Узлы расширений
(Введены в OCaml 4.02, инфиксные обозначения для конструкций, отличных от выражений, добавлены в 4.03, инфиксное обозначение (e1 ;%ext e2) добавлено в 4.04.)
Узлы расширений — это универсальные заглушки в синтаксическом дереве. Они отклоняются проверкой типов и предназначены для «расширения» внешними инструментами, такими как переписыватели -ppx.
Узлы расширений используют ту же концепцию идентификатора и полезной нагрузки, что и атрибуты 12.12.
Первый вид узла расширения используется для «алгебраических» категорий:
|
Второй вид узла расширения может быть использован в структурах и сигнатурах, как в модульном, так и в объектно-ориентированном языках:
|
При использовании инфиксной формы для узлов расширений, когда полезная нагрузка имеет тот же тип (выражение с выражением, шаблон с шаблоном ...), доступна инфиксная форма.
Примеры:
let%foo x = 2 in x + 1 === [%foo let x = 2 in x + 1] begin%foo ... end === [%foo begin ... end] x ;%foo 2 === [%foo x; 2] module%foo M = .. === [%%foo module M = ... ] val%foo x : t === [%%foo: val x : t]
Если эта форма используется вместе с инфиксным синтаксисом для атрибутов, то атрибуты считаются применимыми к полезной нагрузке:
fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@bar ] ];
Для удобства доступен дополнительный сокращенный вариант let%foo x in ..., когда узлы расширений используются для реализации операторов связывания (см. 12.23.4).
Кроме того, строковые литералы {|...|} можно комбинировать с узлами расширений для встраивания фрагментов чужого синтаксиса. Эти фрагменты могут интерпретироваться препроцессором и преобразовываться в код OCaml без необходимости экранирования кавычек. Для них доступен синтаксический ярлык:
{%%foo|...|} === [%%foo{|...|}]
let x = {%foo|...|} === let x = [%foo{|...|}]
let y = {%foo bar|...|bar} === let y = [%foo{bar|...|bar}]
Например, можно использовать {%sql|...|} для представления произвольных SQL-запросов — при условии, что у вас есть ppx-переписыватель, распознающий расширение %sql.
Обратите внимание, что разделитель слов, например {sql|...|sql}, не следует использовать для обозначения того, что расширение используется. Действительно, из кода нельзя понять, имеет ли этот строковый литерал другие семантические значения, чем ожидается. Кроме того, присвоение семантики определенному разделителю ограничивает возможность изменения разделителя для избегания проблем с экранированием.
13.1 Встроенные узлы расширений
(Введены в OCaml 4.03)
Некоторые узлы расширений понимаются самим компилятором:
- «ocaml.extension_constructor» или «extension_constructor» принимают в качестве полезной нагрузки конструктор из расширяемого типа варианта (см. 12.14) и возвращают его слот конструктора расширения.
type t = .. type t += X of int | Y of string let x = [%extension_constructor X] let y = [%extension_constructor Y]
# x <> y;; - : bool = true
© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/extensionnodes.html