expr: value-path | constant |(
expr)
|begin
exprend
|(
expr:
typexpr)
| expr,
expr {,
expr} | ncconstr expr | expr::
expr |[
expr {;
expr}]
|[|
expr {;
expr}|]
|{
label=
expr {;
label=
expr}}
| expr expr | prefix-symbol expr | expr infix-op expr | expr.
label | expr.
label<-
expr | expr.(
expr)
| expr.(
expr)
<-
expr | expr.[
expr]
| expr.[
expr]
<-
expr |if
exprthen
expr [else
expr] |while
exprdo
exprdone
|for
ident=
expr (to
|downto
) exprdo
exprdone
| expr;
expr |match
exprwith
pattern-matching |function
pattern-matching |fun
multiple-matching |try
exprwith
pattern-matching |let
[rec
] let-binding {and
let-binding}in
expr |new
class-path | expr#
method-name |(
expr:>
typexpr)
|(
expr:
typexpr:>
typexpr)
|{<
inst-var-name=
expr {;
inst-var-name=
expr}>}
pattern-matching: pattern [when
expr]->
expr {|
pattern [when
expr]->
expr} multiple-matching: {pattern}+ [when
expr]->
expr let-binding: pattern=
expr | value-name {pattern}+ [:
typexpr]=
expr infix-op: infix-symbol |*
|=
|or
|&
The table below shows the relative precedences and associativity of operators and non-closed constructions. The constructions with higher precedence come first. For infix and prefix symbols, we write ``*...'' to mean ``any symbol starting with *''.
Construction or operator | Associativity |
---|---|
prefix-symbol | -- |
. .( .[ | -- |
function application | left |
constructor application | -- |
- -. (prefix) | -- |
**... | right |
*... /... %... mod | left |
+... -... | left |
:: | right |
@ ^ | right |
comparisons (= == < etc.), all other infix symbols | left |
not | -- |
& && | left |
or || | left |
, | -- |
<- := | right |
if | -- |
; | right |
let match fun function try | -- |
Expressions consisting in a constant evaluate to this constant.
Expressions consisting in an access path evaluate to the value bound to this path in the current evaluation environment. The path can be either a value name or an access path to a value component of a module.
The expressions (
expr )
and begin
expr end
have the same
value as expr. Both constructs are semantically equivalent, but it
is good style to use begin
...end
inside control structures:
if ... then begin ... ; ... end else begin ... ; ... endand
(
...)
for the other grouping situations.
Parenthesized expressions can contain a type constraint, as in (
expr :
type )
. This constraint forces the type of expr to be
compatible with type.
Parenthesized expressions can also contain coercions (
expr [:
type] :>
type )
(see subsection 5.8 below).
Function application is denoted by juxtaposition of expressions. The expression expr1 expr2...exprn evaluates the expressions expr1 to exprn. The expression expr1 must evaluate to a functional value, which is then applied to the values of expr2,...,exprn. The order in which the expressions expr1,...,exprn are evaluated is not specified.
Two syntactic forms are provided to define functions. The first form is introduced by the keyword function:
function pattern1 -> expr1 | ... | patternN -> exprNThis expression evaluates to a functional value with one argument. When this function is applied to a value v, this value is matched against each pattern pattern1 to patternn. If one of these matchings succeeds, that is, if the value v matches the pattern patterni for some i, then the expression expri associated to the selected pattern is evaluated, and its value becomes the value of the function application. The evaluation of expri takes place in an environment enriched by the bindings performed during the matching.
If several patterns match the argument v, the one that occurs first in the function definition is selected. If none of the patterns matches the argument, the exception Match_failure is raised.
The other form of function definition is introduced by the keyword fun:
This expression is equivalent to:fun
pattern1...patternn->
expr
That is, the fun expression above evaluates to a curried function with n arguments: after applying this function n times to the values v1 ... vm, the values will be matched in parallel against the patterns pattern1...patternn. If the matching succeeds, the function returns the value of expr in an environment enriched by the bindings performed during the matchings. If the matching fails, the exception Match_failure is raised.function
pattern1->
...function
patternn->
expr
Cases of a pattern matching (in the function, fun, match and try constructs) can include guard expressions, which are arbitrary boolean expressions that must evaluate to true for the match case to be selected. Guards occur just before the -> token and are introduced by the when keyword:
function pattern1 [when cond1] -> expr1 | ... | patternN [when condN] -> exprNMatching proceeds as described before, except that if the value matches some pattern patterni which has a guard condi, then the expression condi is evaluated (in an environment enriched by the bindings performed during matching). If condi evaluates to true, then expri is evaluated and its value returned as the result of the matching, as usual. But if condi evaluates to false, the matching is resumed against the patterns following patterni.
The let and let rec constructs bind value names locally. The construct
evaluates expr1...exprn in some unspecified order, then matches their values against the patterns pattern1...patternn. If the matchings succeed, expr is evaluated in the environment enriched by the bindings performed during matching, and the value of expr is returned as the value of the whole let expression. If one of the matchings fails, the exception Match_failure is raised.let
pattern1=
expr1and
...and
patternn=
exprnin
expr
An alternate syntax is provided to bind variables to functional values: instead of writing
in a let expression, one may instead writelet
ident=
fun
pattern1...patternm->
expr
let
ident pattern1...patternm=
expr
Recursive definitions of names are introduced by let rec:
The only difference with the let construct described above is that the bindings of names to values performed by the pattern-matching are considered already performed when the expressions expr1 to exprn are evaluated. That is, the expressions expr1 to exprn can reference identifiers that are bound by one of the patterns pattern1,...,patternn, and expect them to have the same value as in expr, the body of the let rec construct.let
rec
pattern1=
expr1and
...and
patternn=
exprnin
expr
The recursive definition is guaranteed to behave as described above if
the expressions expr1 to exprn are function definitions
(fun
... or function
...), and the patterns pattern1...patternn are just value names, as in:
This defines name1...namen as mutually recursive functions local to expr.let
rec
name1=
fun
...and
...and
namen=
fun
...in
expr
The behavior of other forms of let rec definitions is implementation-dependent. The current implementation also supports a certain class of recursive definitions of non-functional values, such as
which binds name1 to the cyclic list 1::2::1::2::..., and name2 to the cyclic list 2::1::2::1::... Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.let
rec
name1=
1
::
name2and
name2=
2
::
name1in
expr
The expression expr1 ;
expr2 evaluates expr1 first, then
expr2, and returns the value of expr2.
The expression if
expr1 then
expr2 else
expr3 evaluates to
the value of expr2 if expr1 evaluates to the boolean true
,
and to the value of expr3 if expr1 evaluates to the boolean
false
.
The else
expr3 part can be omitted, in which case it defaults to
else
()
.
The expression
match expr with pattern1 -> expr1 | ... | patternN -> exprNmatches the value of expr against the patterns pattern1 to patternn. If the matching against patterni succeeds, the associated expression expri is evaluated, and its value becomes the value of the whole
match
expression. The evaluation of
expri takes place in an environment enriched by the bindings
performed during matching. If several patterns match the value of
expr, the one that occurs first in the match
expression is
selected. If none of the patterns match the value of expr, the
exception Match_failure
is raised.
The expression expr1 &
expr2 evaluates to true
if both
expr1 and expr2 evaluate to true
; otherwise, it evaluates to
false
. The first component, expr1, is evaluated first. The
second component, expr2, is not evaluated if the first component
evaluates to false
. Hence, the expression expr1 &
expr2 behaves
exactly as
if
expr1then
expr2else
false
.
The expression expr1 or
expr2 evaluates to true
if one of
expr1 and expr2 evaluates to true
; otherwise, it evaluates to
false
. The first component, expr1, is evaluated first. The
second component, expr2, is not evaluated if the first component
evaluates to true
. Hence, the expression expr1 or
expr2 behaves
exactly as
if
expr1then
true
else
expr2.
The expression while
expr1 do
expr2 done
repeatedly
evaluates expr2 while expr1 evaluates to true
. The loop
condition expr1 is evaluated and tested at the beginning of each
iteration. The whole while
...done
expression evaluates to
the unit value ()
.
The expression for
name =
expr1 to
expr2 do
expr3 done
first evaluates the expressions expr1 and expr2 (the boundaries)
into integer values n and p. Then, the loop body expr3 is
repeatedly evaluated in an environment where name is successively
bound to the values
n, n+1, ..., p-1, p.
The loop body is never evaluated if n > p.
The expression for
name =
expr1 downto
expr2 do
expr3 done
evaluates similarly, except that name is successively bound to the values
n, n-1, ..., p+1, p.
The loop body is never evaluated if n < p.
In both cases, the whole for
expression evaluates to the unit
value ()
.
The expression
try expr with pattern1 -> expr1 | ... | patternN -> exprNevaluates the expression expr and returns its value if the evaluation of expr does not raise any exception. If the evaluation of expr raises an exception, the exception value is matched against the patterns pattern1 to patternn. If the matching against patterni succeeds, the associated expression expri is evaluated, and its value becomes the value of the whole
try
expression. The
evaluation of expri takes place in an environment enriched by the
bindings performed during matching. If several patterns match the value of
expr, the one that occurs first in the try
expression is
selected. If none of the patterns matches the value of expr, the
exception value is raised again, thereby transparently ``passing
through'' the try
construct.
The expression expr1 ,
...,
exprn evaluates to the
n-tuple of the values of expressions expr1 to exprn. The
evaluation order for the subexpressions is not specified.
The expression ncconstr expr evaluates to the variant value whose constructor is ncconstr, and whose argument is the value of expr.
For lists, some syntactic sugar is provided. The expression
expr1 ::
expr2 stands for the constructor (
::
)
applied to the argument (
expr1 ,
expr2 )
, and therefore
evaluates to the list whose head is the value of expr1 and whose tail
is the value of expr2. The expression [
expr1 ;
...;
exprn ]
is equivalent to expr1 ::
...::
exprn ::
[]
, and therefore evaluates to the list whose elements are the
values of expr1 to exprn.
The expression {
label1 =
expr1 ;
...;
labeln =
exprn }
evaluates to the record value
{
label1 =
v1 ;
...;
labeln =
vn }
,
where vi is the value of expri for i = 1, ..., n.
The labels label1 to labeln must all belong to the same record
types; all labels belonging to this record type must appear exactly
once in the record expression, though they can appear in any
order. The order in which expr1 to exprn are evaluated is not
specified.
The expression expr1 .
label evaluates expr1 to a record
value, and returns the value associated to label in this record
value.
The expression expr1 .
label <-
expr2 evaluates expr1 to a record
value, which is then modified in-place by replacing the value
associated to label in this record by the value of
expr2. This operation is permitted only if label has been
declared mutable
in the definition of the record type. The whole
expression expr1 .
label <-
expr2 evaluates to the unit value
()
.
The expression [|
expr1 ;
...;
exprn |]
evaluates to
a n-element array, whose elements are initialized with the values of
expr1 to exprn respectively. The order in which these
expressions are evaluated is unspecified.
The expression expr1 .(
expr2 )
returns the value of element
number expr2 in the array denoted by expr1. The first element
has number 0; the last element has number n-1, where n is the
size of the array. The exception Invalid_argument is raised if the
access is out of bounds.
The expression expr1 .(
expr2 )
<-
expr3 modifies in-place
the array denoted by expr1, replacing element number expr2 by
the value of expr3. The exception Invalid_argument is raised if
the access is out of bounds. The value of the whole expression is ()
.
The expression expr1 .[
expr2 ]
returns the value of character
number expr2 in the string denoted by expr1. The first character
has number 0; the last character has number n-1, where n is the
length of the string. The exception Invalid_argument is raised if the
access is out of bounds.
The expression expr1 .[
expr2 ]
<-
expr3 modifies in-place
the string denoted by expr1, replacing character number expr2 by
the value of expr3. The exception Invalid_argument is raised if
the access is out of bounds. The value of the whole expression is ()
.
Symbols from the class infix-symbols
, as well as the keywords
*, =, or and &, can appear in infix position (between two
expressions). Symbols from the class prefix-symbols
can appear in prefix position (in front of an expression).
Infix and prefix symbols do not have a fixed meaning: they are simply
interpreted as applications of functions bound to the names
corresponding to the symbols. The expression prefix-symbol expr is
interpreted as the application (
prefix-symbol )
expr. Similarly, the expression expr1 infix-symbol expr2 is
interpreted as the application (
infix-symbol )
expr1 expr2.
The table below lists the symbols defined in the initial environment
and their initial meaning. (See the description of the standard
library module Pervasive in chapter 16 for more
details). Their meaning may be changed at any time using
let
(
infix-op )
name1 name2 =
...
Operator | Initial meaning |
---|---|
+ | Integer addition. |
- (infix) | Integer subtraction. |
- (prefix) | Integer negation. |
* | Integer multiplication. |
/ | Integer division. Raise Division_by_zero if second argument is zero. The result is unspecified if either argument is negative. |
mod | Integer modulus. Raise Division_by_zero if second argument is zero. The result is unspecified if either argument is negative. |
land | Bitwise logical ``and'' on integers. |
lor | Bitwise logical ``or on integers. |
lxor | Bitwise logical ``exclusive or'' on integers. |
lsl | Bitwise logical shift left on integers. |
lsr | Bitwise logical shift right on integers. |
asr | Bitwise arithmetic shift right on integers. |
+. | Floating-point addition. |
-. (infix) | Floating-point subtraction. |
-. (prefix) | Floating-point negation. |
*. | Floating-point multiplication. |
/. | Floating-point division. |
** | Floating-point exponentiation. |
@ | List concatenation. |
^ | String concatenation. |
! | Dereferencing (return the current contents of a reference). |
:= | Reference assignment (update the reference given as first argument with the value of the second argument). |
= | Structural equality test. |
<> | Structural inequality test. |
== | Physical equality test. |
!= | Physical inequality test. |
< | Test ``less than''. |
<= | Test ``less than or equal''. |
> | Test ``greater than''. |
>= | Test ``greater than or equal'' |
The expression new
class-path denotes a function that takes some
initialization arguments and returns a new object of class
class-path.
The expression expr #
method-name invokes the method
method-name of the object denoted by expr.
The type of an object can be coerced (weakened) to a supertype.
The expression (
expr :>
typexpr )
coerces the expression expr
to type typexpr.
The expression (
expr :
typexpr1 :>
typexpr2 )
coerces the
expression expr from type typexpr1 to type typexpr2.
The former operator will sometimes fail to coerce an expression expr
from a type t1 to a type t2 even if type t1 is a subtype of type
t2. In this case, the latter operator should be used.
In a class definition, coercion to the type this class defines is the identity, as this type abbreviation is not yet completely defined.
An object can be duplicated using the library function Oo.copy
(see section 17.17). Inside a method, the expression
{<
inst-var-name =
expr {;
inst-var-name =
expr} >}
returns a copy of self with the given instance variables replaced by
the values of the associated expressions; other instance variables
have the same value in the returned object as in self.