10.13 Узлы расширения
(Введены в OCaml 4.02, инфиксные обозначения для конструкций, отличных от выражений, добавлены в 4.03, инфиксное обозначение (e1 ;%ext e2) добавлено в 4.04.)
Узлы расширения — это универсальные заглушки в синтаксическом дереве. Они отклоняются проверяющим типы и предназначены для «расширения» внешними инструментами, такими как переписыватели -ppx.
Узлы расширения используют ту же концепцию идентификатора и полезной нагрузки, что и атрибуты 10.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 ... при использовании узлов расширения для реализации операторов связывания (см. 10.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}, не следует использовать для обозначения того, что расширение используется. Действительно, из кода пользователь не может определить, имеет ли этот строковый литерал другую семантику, чем ожидается. Кроме того, предоставление семантики определенному разделителю ограничивает свободу изменения разделителя для предотвращения проблем с экранированием.
10.13.1 Встроенные узлы расширения
(Введены в OCaml 4.03)
Некоторые узлы расширения понимаются самим компилятором:
- «ocaml.extension_constructor» или «extension_constructor» принимают в качестве полезной нагрузки конструктор из расширяемого типа варианта (см. 10.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/4.14/htmlman/extensionnodes.html