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 let x = 23;;let x = 23 in x + 7;;value x = 23;let x = 23 in x + 7; -
В интерфейсах модулей вместо
valследует использовать тожеvalue.Ocaml Revised val x : int;;value x : int;
-
Появился ещё один способ определить последовательность операторов: за ключевым словом
doследует последовательность операторов, разделённых;, окружённая{и}(допускается;после последнего оператора).Ocaml Revised e1; e2; e3; e4do { e1; e2; e3; e4 } -
Тело
forиwhileможет быть оформлено с тем же синтаксисом:Ocaml Revised while e1 do e2; e3; e4 donewhile e1 do { e2; e3; e4 }
-
Скобки обязательны в туплах:
Ocaml Revised 1, "hello", World(1, "hello", World)` -
Списки всегда окружены
[и]. Их синтаксис:list ::= [ elem-list opt-cons ] elem-list ::= expression ; elem-list | expression opt-cons ::= :: expression | (empty)
-
Список – последовательность выражений, разделённых точкой с запятой, опционально завершённых
::и выражением, и всё заключено в квадратные скобки. Например:Ocaml Revised x::y[x::y][x; y; z][x; y; z]x::y::z::t[x::[y::[z::t]]]x::y::z::t[x; y; z :: t] -
Заметьте, есть два способа записать последний случай.
Некоторые синтаксические конструкции используют понятие "irrefutable patterns". Сопоставление значений таким паттернам всегда успешно. Вот что может называться irrefutable pattern:
- Переменная.
- Символ
_, соответствующий любому значению. - Конструктор тупла
(). - Тупл с irrefutable patterns.
- Запись с irrefutable patterns.
- Irrefutable pattern с ограничением типа (type constraint).
Заметьте, что термин "irrefutable" применяется не ко всем паттернам,
сопоставление с которыми всегда удачно: например, тип с ровно одним
конструктором (кроме () : unit) не является irrefutable.
-
Ключевое слово
functionбольше не существует, используйтеfunвместо него. -
При паттерн матчинге конструкций
fun,matchиtryвсе варианты должны быть заключены в квадратные скобки: открывающаяся скобка[перед первым вариантом и закрывающаяся]после последнего:Ocaml Revised match e with p1 -> e | p2 -> e2;;match e with [ p1 -> e1 | p2 -> e2 ];fun x -> x;;fun [x -> x]; -
Однако, если вариант только один и паттерн является irrefutable, квадратные скобки не обязательны. Следующие примеры работают одинаково в оригинальном и revised синтаксисах:
Ocaml Revised fun x -> xfun x -> xfun {foo=(y, _)} -> yfun {foo=(y, _)} -> y -
Каррированный паттерн матчинг может быть оформлен через
fun, но только с irrefutable паттернами:Ocaml Revised fun x (y, z) -> tfun x (y, z) -> tfun x y (C z) -> tfun x y -> fun [C z -> t] -
Теперь наконец-то стало возможно написать пустую функцию, кидающую исключение
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 x.f <- yx.f := y -
Тип
refобъявлен как запись с одним полемval, вместоcontents. Оператор!более не существует, и присваивать значения ссылкам следует так же, как и любым другим изменяемым записям:Ocaml Revised x := !x + yx.val := x.val + y
-
Конструкторы параметрических типов записываются перед параметрами, а параметры каррируются:
Ocaml Revised int listlist int('a, bool) Hashtbl.tHashtbl.t 'a booltype 'a foo = 'a list list;;type foo 'a = list (list 'a); -
В туплах из типов обязательны скобки:
Ocaml Revised int * bool(int * bool) -
В объявлении вариантного типа варианты должны быть заключены в квадратные скобки:
Ocaml Revised type t = A of i | B;;type t = [ A of i | B ]; -
Возможно создать пустой (ненаселённый) тип, без конструктора:
type foo = []; -
Существует разница между конструкторами с несколькими параметрами и конструкторами с одним параметром, являющимся туплом. При объявлении конструктора с несколькими параметрами они разделены ключевым словом
and. В выражениях и при паттерн-матчинге параметры конструктора каррируются:Ocaml Revised type t = C of t1 * t2;;type t = [ C of t1 and t2 ];C (x, y);;C x y; -
Объявление конструктора с одним параметром-туплом осуществляется с использованием тупла типов. В выражениях и паттернах параметры не каррируются, а матчатся как обычный тупл:
Ocaml Revised type t = D of (t1 * t2);;type t = [ D of (t1 * t2) ];D (x, y);;D (x, y); -
Предопределённые конструкторы булевого типа
TrueиFalseначинаются с заглавной буквы, как любые другие конструкторы. -
В записях ключевое слово
mutableдолжно быть после двоеточия:Ocaml Revised type t = {mutable x : t1};;type t = {x : mutable t1};
-
Применение модулей теперь каррируется:
Ocaml Revised type t = Set.Make(M).t;;type t = (Set.Make M).t;Объявляются с указанием на открытость/закрытость типа:
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 if a then bif a then b else () -
Булевые операторы
orиandзаписываются только как||и&&:Ocaml Revised a or b & ca || b && c -
В файлах интерфейса labeled аргументы надо указывать с тильдой:
Ocaml Revised val f: x:int -> unit value f: ~x:int -> unit
-
Streams и паттерны в stream parsers окружаются
[:и:]вместо[<and>]. -
Компонент stream'а записывается с обратным апострофом вместо обычного:
Ocaml Revised [< '1; '2; s; '3 >][: \`1; \`2; s; \`3 :] -
Варианты в парсере заключаются в
[and], как вfun,matchиtry. Если вариант только один, скобки не обязательны:Ocaml Revised parser [< `Foo >] -> e | [< p = f >] -> fparser [ [: `x :] -> x ]parser [< 'x >] -> xparser [: `x :] -> x -
Возможно написать пустой парсер, кидающий исключение
Stream.Failure, какой бы поток к нему ни применили. Пустой паттернг матчинг тоже кидаетStream.Failure:parser [] match e with parser []
2011-03-26 13:08
-