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