Revised syntax – альтернатива классическому original syntax в OCaml. Он проще, регулярнее, логичнее, и исправляет некоторые недостатки оригинального синтаксиса, иногда вызывающие трудноуловимые баги. Этот синтаксис был назван "righteous", но название не прижилось.
Интерактивно:
$ ocaml
Objective Caml version 3.11.1
# #load "dynlink.cma";;
# #load "camlp4r.cma";;
Camlp4 Parsing version 3.11.1
# value test = do { (); 1 };
value test : int = 1
#
При компиляции вызовом ocamlc, ocamlopt или ocamlfind – добавьте -pp camlp4r в строку компиляции:
$ ocamlfind ocamlopt -pp camlp4r mymodule.ml -o myexecutable
При компиляции через ocamlbuild добавьте в файл _tags тэг camlp4r для файлов, написанных в revised syntax, например,
<*.ml*> : camlp4r
Однако если добавлять тэг для всех *.ml*, а в проекте есть .ml-файлы, сгенерированные ocamllex/ocamlyacc (в original syntax), нужно будет исключить их:
<mylexer.ml> | <myparser.ml{,i}> : -camlp4r, camlp4o
Точка с запятой завершает фразу. Двойная точка с запятой – не распознаётся. Последовательности операторов имеют другой синтаксис, и точка с запятой в конце фразы не будет перепутана с точкой с запятой, разделяющей последовательность операторов.
Объявление глобального значения производится ключевым словом value. Слово let зарезервировано исключительно для конструкции let..in:
| Ocaml | Revised |
| |
| |
В интерфейсах модулей вместо val следует использовать тоже value.
| Ocaml | Revised |
| |
Появился ещё один способ определить последовательность операторов: за ключевым словом do следует последовательность операторов, разделённых ;, окружённая { и } (допускается ; после последнего оператора).
| Ocaml | Revised |
| |
Тело for и while может быть оформлено с тем же синтаксисом:
| Ocaml | Revised |
| |
Скобки обязательны в туплах:
| Ocaml | Revised |
| |
Списки всегда окружены [ и ]. Их синтаксис:
list ::= [ elem-list opt-cons ] elem-list ::= expression ; elem-list | expression opt-cons ::= :: expression | (empty)
Список – последовательность выражений, разделённых точкой с запятой, опционально завершённых :: и выражением, и всё заключено в квадратные скобки. Например:
| Ocaml | Revised |
| |
| |
| |
| |
Заметьте, есть два способа записать последний случай.
Некоторые синтаксические конструкции используют понятие "irrefutable patterns". Сопоставление значений таким паттернам всегда успешно. Вот что может называться irrefutable pattern:
Переменная.
Символ _, соответствующий любому значению.
Конструктор тупла ().
Тупл с irrefutable patterns.
Запись с irrefutable patterns.
Irrefutable pattern с ограничением типа (type constraint).
Заметьте, что термин "irrefutable" применяется не ко всем паттернам, сопоставление с которыми всегда удачно: например, тип с ровно одним конструктором (кроме () : unit) не является irrefutable.
Ключевое слово function больше не существует, используйте fun вместо него.
При паттерн матчинге конструкций fun, match и try все варианты должны быть заключены в квадратные скобки: открывающаяся скобка [ перед первым вариантом и закрывающаяся ] после последнего:
| Ocaml | Revised |
| |
| |
Однако, если вариант только один и паттерн является irrefutable, квадратные скобки не обязательны. Следующие примеры работают одинаково в оригинальном и revised синтаксисах:
| Ocaml | Revised |
| |
| |
Каррированный паттерн матчинг может быть оформлен через fun, но только с irrefutable паттернами:
| Ocaml | Revised |
| |
| |
Теперь наконец-то стало возможно написать пустую функцию, кидающую исключение Match_failure, какой бы аргумент к ней ни применили, пустой match, кидающий Match_failure после вычисления значения выражения, и пустой try, эквивалентный выражению без try:
fun []
match e with []
try e with []
Паттерны в let и value должны быть irrefutable. Следующее выражение, написанное в original syntax:
let f (x::y) = ...
в revised syntax должно быть переписано так:
let f = fun [ [x::y] -> ...
Конструкция where вернулась, но только с одной привязкой: можно написать e where x = y, но не where x = y and z = t
Инструкция <- записывается как :=:
| Ocaml | Revised |
| |
Тип ref объявлен как запись с одним полем val, вместо contents. Оператор ! более не существует, и присваивать значения ссылкам следует так же, как и любым другим изменяемым записям:
| Ocaml | Revised |
| |
Конструкторы параметрических типов записываются перед параметрами, а параметры каррируются:
| Ocaml | Revised |
| |
| |
| |
В туплах из типов обязательны скобки:
| Ocaml | Revised |
| |
В объявлении вариантного типа варианты должны быть заключены в квадратные скобки:
| Ocaml | Revised |
| |
Возможно создать пустой (ненаселённый) тип, без конструктора:
type foo = [];
Существует разница между конструкторами с несколькими параметрами и конструкторами с одним параметром, являющимся туплом. При объявлении конструктора с несколькими параметрами они разделены ключевым словом and. В выражениях и при паттерн-матчинге параметры конструктора каррируются:
| Ocaml | Revised |
| |
| |
Объявление конструктора с одним параметром-туплом осуществляется с использованием тупла типов. В выражениях и паттернах параметры не каррируются, а матчатся как обычный тупл:
| Ocaml | Revised |
| |
| |
Предопределённые конструкторы булевого типа True и False начинаются с заглавной буквы, как любые другие конструкторы.
В записях ключевое слово mutable должно быть после двоеточия:
| Ocaml | Revised |
| |
Применение модулей теперь каррируется:
| Ocaml | Revised |
| |
Объявляются с указанием на открытость/закрытость типа:
type poly_open = [> `A | `B of (int * string) ];
type poly_eq = [= `A |`B of (int * string) ];
type poly_closed = [< `A | `B of (int * string) ];
Объекты объявляются с использованием value для полей:
# object
value my_field = 123;
method my_method () = my_field;
end;
- : < my_method : unit -> int > = <obj>
Часть else теперь обязательна в if:
| Ocaml | Revised |
| |
Булевые операторы or и and записываются только как || и &&:
| Ocaml | Revised |
| |
Streams и паттерны в stream parsers окружаются [: и :] вместо [< and >].
Компонент stream'а записывается с обратным апострофом вместо обычного:
| Ocaml | Revised |
| |
Варианты в парсере заключаются в [ and ], как в fun, match и try. Если вариант только один, скобки не обязательны:
| Ocaml | Revised |
| |
| |
Возможно написать пустой парсер, кидающий исключение Stream.Failure, какой бы поток к нему ни применили. Пустой паттернг матчинг тоже кидает Stream.Failure:
parser []
match e with parser []
2011-03-26 13:08