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.1).
Кроме того, строки в кавычках {|...|} могут быть объединены с узлами расширения для вставки фрагментов чужого синтаксиса. Эти фрагменты могут интерпретироваться препроцессором и преобразовываться в код 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}, не следует использовать для обозначения того, что расширение используется. Действительно, из кода нельзя увидеть, имеет ли эта строковая литерал другой смысл, чем ожидается. Кроме того, придание семантики конкретному разделителю ограничивает свободу изменения разделителя, чтобы избежать проблем с экранированием.
12.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-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/extensionnodes.html