The revised syntax
The revised syntax is an alternative syntax of OCaml. It is close to the normal syntax. We present here only the differences between the two syntaxes.
Notice that there is a simple way to know how the normal syntax is written in revised syntax: write the code in a file "foo.ml" in normal syntax and type, in a shell:
camlp5o pr_r.cmo pr_rp.cmo foo.ml
And, conversely, how a file "bar.ml" written in revised syntax is displayed in normal syntax:
camlp5r pr_o.cmo pr_op.cmo bar.ml
Even simpler, without creating a file:
camlp5o pr_r.cmo pr_op.cmo -impl - ... type in normal syntax ... ... type control-D ... camlp5r pr_o.cmo pr_rp.cmo -impl - ... type in revised syntax ... ... type control-D ...
Lexing
- The character quote (') can be written without backslash:
OCaml Revised '\'' '''
Modules, Structure and Signature items
- Structure and signature items always end with a single semicolon which is required.
- In structures, the declaration of a value is introduced by the
keyword "value", instead of "let":
OCaml Revised let x = 42;; value x = 42; let x = 42 in x + 7;; let x = 42 in x + 7; - In signatures, the declaration of a value is also introduced by
the keyword "value", instead of "val":
OCaml Revised val x : int;; value x : int; - In signatures, abstract module types are represented by a quote
and an (any) identifier:
OCaml Revised module type MT;; module type MT = 'a; - Functor application uses currying. Parentheses are not
required for the parameters:
OCaml Revised type t = Set.Make(M).t;; type t = (Set.Make M).t; module M = Mod.Make (M1) (M2);; module M = Mod.Make M1 M2; - It is possible to group several declarations together either in
an interface or in an implementation by enclosing them between
"declare" and "end" (this is useful when using syntax extensions
to generate several declarations from one). Example in an
interface:
declare type foo = [ Foo of int | Bar ]; value f : foo -> int; end;
Expressions and Patterns
Imperative constructions
- The sequence is introduced by the keyword "do" followed by "{"
and terminated by "}"; it is possible to put a semicolon after the
last expression:
OCaml Revised e1; e2; e3; e4 do { e1; e2; e3; e4 } - The "do" after the "while" loop and the "for" loop are followed
by a "{" and the loop end with "}"; it is possible to put a
semicolon after the last expression:
OCaml Revised while e1 do while e1 do { e1; e2; e3 e1; e2; e3 done } for i = e1 to e2 do for i = e1 to e2 do { e1; e2; e3 e1; e2; e3 done }
Tuples and Lists
- Parentheses are required in tuples:
OCaml Revised 1, "hello", World (1, "hello", World) - Lists are always enclosed with brackets. A list is a left
bracket, followed by a list of elements separated with semicolons,
optionally followed by colon-colon and an element, and ended by a
right bracket. Warning: the colon-colon is not an infix but is
just part of the syntactic construction.
OCaml Revised x :: y [x :: y] [x; y; z] [x; y; z] x :: y :: z :: t [x; y; z :: t]
Records
- In record update, parentheses are required around the initial
expression:
OCaml Revised {e with field = a} {(e) with field = a} - It is allowable to use function binding syntax in record field
definitions:
OCaml Revised {field = fun a -> e} {field a = e}
Irrefutable patterns
An irrefutable pattern is a pattern which is syntactically visible and never fails. They are used in some syntactic constructions. It is either:
- A variable,
- The wildcard "_",
- The constructor "()",
- A tuple with irrefutable patterns,
- A record with irrefutable patterns,
- A type constraint with an irrefutable pattern.
Notice that this definition is only syntactic: a constructor belonging to a type having only one constructor is not considered as an irrefutable pattern (except "()").
Constructions with matching
- The keyword "function" no longer exists. Only "fun" is used.
- The pattern matching, in constructions with "fun", "match" and
"try" is closed with brackets: an open bracket "[" before the
first case, and a close bracket "]" after the last case:
OCaml Revised match e with match e with p1 -> e1 [ p1 -> e1 | p2 -> e2 | p2 -> e2 ] OCaml Revised fun x -> x fun x -> x fun {foo=(y, _)} -> y fun {foo=(y, _)} -> y - It is possible to write the empty function which always raises the
exception "Match_failure" when a parameter is applied. It is also possible to write and
empty "match", raising "Match_failure" after having evaluated its
expression and the empty "try", equivalent to its expression
without try:
fun [] match e with [] try e with []
- The patterns after "let" and "value" must be irrefutable. The
following OCaml expression:
let f (x::y) = ...
must be written:let f = fun [ [x::y] -> ...
- It is possible to use a construction "where", equivalent to "let",
but usable only when where is only one binding. The expression:
e1 where p = e
is equivalent to:let p = e in e1
Mutables and Assignment
- The statement "<-" is written ":=":
OCaml Revised x.f <- y x.f := y - The "ref" type is declared as a record type with one field named
"val", instead of "contents". The operator "!" does not exist any
more, and references are assigned like the other mutables:
OCaml Revised x := !x + y x.val := x.val + y
Miscellaneous
- The "else" is required in the "if"
statement:
OCaml Revised if a then b if a then b else () - The boolean operations "or" and "and" can only
be written with "||" and "&&":
OCaml Revised a or b & c a || b && c a || b && c a || b && c - No more "begin end" construction. One must use parentheses.
- The operators as values are written with an backslash:
OCaml Revised (+) \+ (mod) \mod - Nested "as" patterns require parenthesis:
OCaml Revised function Some a as b, c -> fun [ ((Some a as b), c) -> ... ... OCaml Revised function Some a as b -> fun [ Some a as b -> ... ... - The operators with special characters are not automatically infix. To define infixes, use syntax extensions.
Types and Constructors
- The type constructors are before their type parameters, which
are curryfied:
OCaml Revised int list list int ('a, bool) Hashtbl.t Hashtbl.t 'a bool type 'a foo = 'a list list type foo 'a = list (list 'a) - The abstract types are represented by an unbound type variable:
OCaml Revised type 'a foo;; type foo 'a = 'b; type bar;; type bar = 'a; - Parentheses are required in tuples of types:
OCaml Revised int * bool (int * bool) - In declarations of a concrete type, brackets must enclose the
constructor declarations:
OCaml Revised type t = A of i | B;; type t = [ A of i | B ]; - It is possible to make the empty type, without constructor:
type foo = [];
- There is a syntax difference between data constructors with
several parameters and data constructors with one parameter of type
tuple:
The declaration of a data constructor with several parameters is done by separating the types with "and". In expressions and patterns, these constructor parameters must be curryfied: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); - The bool constructors start with an uppercase letter. The identifiers
"true" and "false" are not keywords:
OCaml Revised true && false True && False - In record types, the keyword "mutable" must appear after the
colon:
OCaml Revised type t = {mutable x : t1};; type t = {x : mutable t1}; - Manifest types are with "==":
OCaml Revised type 'a t = 'a option = type t 'a = option 'a == None [ None | Some of 'a | Some of 'a ] - Polymorphic types start with "!":
OCaml Revised type t = type t = { f : 'a . 'a list } { f : ! 'a . list 'a }
Streams and Parsers
- The streams and the stream patterns are bracketed with "[:" and ":]" instead of "[<" and ">]".
- The stream component "terminal" is written with a back-quote
instead of a quote:
OCaml Revised [< '1; '2; s; '3 >] [: `1; `2; s; `3 :] - The cases of parsers are bracketed with "[" and
"]", as with "fun", "match" and "try". If there is one
case, the brackets are not required:
OCaml Revised parser parser [< 'Foo >] -> e [ [: `Foo :] -> e | [< p = f >] -> f;; | [: p = f :] -> f ]; parser [< 'x >] -> x;; parser [: `x :] -> x; - It is possible to write the empty parser raising the exception
"Stream.Failure" whatever parameter is applied, and the empty
stream matching always raising "Stream.Failure":
parser [] match e with parser []
- In normal syntax, the error indicator starts with a double question
mark, in revised syntax with a simple question mark:
OCaml Revised parser parser [< '1; '2 ?? "error" >] -> [: `1; `2 ? "error" :] -> ... ... - In normal syntax, the component optimization starts with
"?!", in revised syntax with "!":
OCaml Revised parser parser [< '1; '2 ?! >] -> [: `1; `2 ! :] -> ... ...
Classes and Objects
- Object items end with a single semicolon which is required.
- Class type parameters follow the class identifier:
OCaml Revised class ['a, 'b] point = ... class point ['a, 'b] = ... class c = [int] color;; class c = color [int]; - In the type of class with parameters, the type of the parameters
are between brackets. Example in signature:
OCaml Revised class c : int -> point;; class c : [int] -> point; - The keywords "virtual" and "private" must be in this order:
OCaml Revised method virtual private m : method virtual private m : ... ... method private virtual m : method virtual private m : ... ... - Object variables are introduced with "value" instead of "val":
OCaml Revised object val x = 3 end object value x = 3; end - Type constraints in objects are introduced with "type" instead of
"constraint":
OCaml Revised object constraint 'a = int end object type 'a = int; end
Labels and Variants
- Labels in types must start with "~":
OCaml Revised val x : num:int -> bool;; value x : ~num:int -> bool; - Types whose number of variants are fixed start with "[ =":
OCaml Revised type t = [`On | `Off];; type t = [ = `On | `Off]; - The "[" and the "<" in variant types must
not be sticked:
OCaml Revised type t = [< `Foo | `Bar ];; type t = [ < `Foo | `Bar ];