Expressions

6.7 | Expressions

`expr` | ::= | `value-path`
| | | `constant`
| | | `(` `expr` `)`
| | | `begin` `expr` `end`
| | | `(` `expr` `:` `typexpr` `)`
| | | `expr` `,` `expr` { `,` `expr` }
| | | `constr` `expr`
| | | ````tag-name` `expr`
| | | `expr` `::` `expr`
| | | `[` `expr` { `;` `expr` } `]`
| | | `[|` `expr` { `;` `expr` } `|]`
| | | `{` `field` `=` `expr` { `;` `field` `=` `expr` } `}`
| | | `{` `expr` `with` `field` `=` `expr` { `;` `field` `=` `expr` } `}`
| | | `expr` { `argument` }+
| | | `prefix-symbol` `expr`
| | | `expr` `infix-op` `expr`
| | | `expr` `.` `field`
| | | `expr` `.` `field` `<-` `expr`
| | | `expr` `.(` `expr` `)`
| | | `expr` `.(` `expr` `)` `<-` `expr`
| | | `expr` `.[` `expr` `]`
| | | `expr` `.[` `expr` `]` `<-` `expr`
| | | `if` `expr` `then` `expr` [ `else` `expr` ]
| | | `while` `expr` `do` `expr` `done`
| | | `for` `ident` `=` `expr` ( `to` | `downto` ) `expr` `do` `expr` `done`
| | | `expr` `;` `expr`
| | | `match` `expr` `with` `pattern-matching`
| | | `function` `pattern-matching`
| | | `fun` `multiple-matching`
| | | `try` `expr` `with` `pattern-matching`
| | | `let` [`rec`] `let-binding` { `and` `let-binding` } `in` `expr`
| | | `new` `class-path`
| | | `expr` `#` `method-name`
| | | `inst-var-name`
| | | `inst-var-name` `<-` `expr`
| | | `(` `expr` `:>` `typexpr` `)`
| | | `(` `expr` `:` `typexpr` `:>` `typexpr` `)`
| | | `{<` `inst-var-name` `=` `expr` { `;` `inst-var-name` `=` `expr` } `>}`
| | | `assert` `expr`
| | | `lazy` `expr`
`argument` | ::= | `expr`
| | | `~` `label-name`
| | | `~` `label-name` `:` `expr`
| | | `?` `label-name`
| | | `?` `label-name` `:` `expr`

`pattern-matching` | ::= | [ `|` ] `pattern` [`when` `expr`] `->` `expr` { `|` `pattern` [`when` `expr`] `->` `expr` }
`multiple-matching` | ::= | { `parameter` }+ [`when` `expr`] `->` `expr`
`let-binding` | ::= | `pattern` `=` `expr`
| | | `value-name` { `parameter` } [`:` `typexpr`] `=` `expr`
`parameter` | ::= | `pattern`
| | | `~` `label-name`
| | | `~` `(` `label-name` [`:` `typexpr`] `)`
| | | `~` `label-name` `:` `pattern`
| | | `?` `label-name`
| | | `?` `(` `label-name` [`:` `typexpr`] [`=` `expr`] `)`
| | | `?` `label-name` `:` `pattern`
| | | `?` `label-name` `:` `(` `pattern` [`:` `typexpr`] [`=` `expr`] `)`

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, constructor application, `assert lazy` | left
`- -.` (prefix) | --
`**`... | right
`*`...`/`...`%`...`mod` | left
`+`...`-`... | left
`::` | right
`@`...`^`... | right
comparisons (`= == <` etc.), all other infix symbols | left
`& &&` | left
`or ||` | left
`,` | --
`<- :=` | right
`if` | --
`;` | right
`let match fun function try` | --

6.7.1 | Basic expressions

Constants

Expressions consisting in a constant evaluate to this constant.

Value paths

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.

Parenthesized expressions

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 ... ; ... end

and `(` ... `)` 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 6.7.5 below).

Function application

Function application is denoted by juxtaposition of (possibly labeled) expressions. The expression `expr` `argument`1 ... `argument`n evaluates the expression `expr` and those appearing in `argument`1 to `argument`n. The expression `expr` must evaluate to a functional value `f`, which is then applied to the values of `argument`1, ..., `argument`n.
The order in which the expressions `expr`, `argument`1, ..., `argument`n are evaluated is not specified.
Arguments and parameters are matched according to their respective labels. Argument order is irrelevant, except among arguments with the same label, or no label.
If a parameter is specified as optional (label prefixed by `?`) in the type of `expr`, the corresponding argument will be automatically wrapped with the constructor `Some`, except if the argument itself is also prefixed by `?`, in which case it is passed as is. If a non-labeled argument is passed, and its corresponding parameter is preceded by one or several optional parameters, then these parameters are defaulted, i.e. the value `None` will be passed for them. All other missing parameters (without corresponding argument), both optional and non-optional, will be kept, and the result of the function will still be a function of these missing parameters to the body of `f`.
As a special case, if the function has a known arity, all the arguments are unlabeled, and their number matches the number of non-optional parameters, then labels are ignored and non-optional parameters are matched in their definition order. Optional arguments are defaulted.
In all cases but exact match of order and labels, without optional parameters, the function type should be known at the application point. This can be ensured by adding a type constraint. Principality of the derivation can be checked in the `-principal` mode.

Function definition

Two syntactic forms are provided to define functions. The first form is introduced by the keyword `function`:

`function` | pattern1 | `->` | expr1
`|` | ...
`|` | patternn | `->` | exprn

This 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 `pattern`1 to `pattern`n. If one of these matchings succeeds, that is, if the value v matches the pattern `pattern`i for some i, then the expression `expr`i associated to the selected pattern is evaluated, and its value becomes the value of the function application. The evaluation of `expr`i 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`:
`fun` `parameter`1 ... `parameter`n `->` `expr`
This expression is equivalent to:
`fun` `parameter`1 `->` ... `fun` `parameter`n `->` `expr`
Functions of the form `fun` `optlabel` `(` `pattern` `=` `expr`0 `)` `->` `expr` are equivalent to

`fun` `optlabel` `x` `->` `let` `pattern` `=` `match` `x` `with` `Some` `x` `->` `x` `|` `None` `->` `expr`0 `in` `expr`

where `x` is a fresh variable. When `expr`0 will be evaluated is left unspecified.
After these two transformations, expressions are of the form
`fun` [`label`1] `pattern`1 `->` ... `fun` [`label`n] `pattern`n `->` `expr`
If we ignore labels, which will only be meaningful at function application, this is equivalent to
`function` `pattern`1 `->` ... `function` `pattern`n `->` `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 `pattern`1 ... `pattern`n. 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.

Guards in pattern-matchings

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] | `->` | exprn

Matching proceeds as described before, except that if the value matches some pattern `pattern`i which has a guard `cond`i, then the expression `cond`i is evaluated (in an environment enriched by the bindings performed during matching). If `cond`i evaluates to `true`, then `expr`i is evaluated and its value returned as the result of the matching, as usual. But if `cond`i evaluates to `false`, the matching is resumed against the patterns following `pattern`i.

Local definitions

The `let` and `let rec` constructs bind value names locally. The construct
`let` `pattern`1 `=` `expr`1 `and` ... `and` `pattern`n `=` `expr`n `in` `expr`
evaluates `expr`1 ... `expr`n in some unspecified order, then matches their values against the patterns `pattern`1 ... `pattern`n. 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.
An alternate syntax is provided to bind variables to functional values: instead of writing
`let` `ident` `=` `fun` `parameter`1 ... `parameter`m `->` `expr`
in a `let` expression, one may instead write
`let` `ident` `parameter`1 ... `parameter`m `=` `expr`
Recursive definitions of names are introduced by `let rec`:
`let` `rec` `pattern`1 `=` `expr`1 `and` ... `and` `pattern`n `=` `expr`n `in` `expr`
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 `expr`1 to `expr`n are evaluated. That is, the expressions `expr`1 to `expr`n can reference identifiers that are bound by one of the patterns `pattern`1, ..., `pattern`n, and expect them to have the same value as in `expr`, the body of the `let rec` construct.
The recursive definition is guaranteed to behave as described above if the expressions `expr`1 to `expr`n are function definitions (`fun` ... or `function` ...), and the patterns `pattern`1 ... `pattern`n are just value names, as in:
`let` `rec` `name`1 `=` `fun` ... `and` ... `and` `name`n `=` `fun` ... `in` `expr`
This defines `name`1 ... `name`n as mutually recursive functions local to `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, as explained in section 7.3.

6.7.2 | Control structures

Sequence

The expression `expr`1 `;` `expr`2 evaluates `expr`1 first, then `expr`2, and returns the value of `expr`2.

Conditional

The expression `if` `expr`1 `then` `expr`2 `else` `expr`3 evaluates to the value of `expr`2 if `expr`1 evaluates to the boolean `true`, and to the value of `expr`3 if `expr`1 evaluates to the boolean `false`.
The `else` `expr`3 part can be omitted, in which case it defaults to `else` `()`.

Case expression

The expression

`match` | expr
`with` | pattern1 | `->` | expr1
`|` | ...
`|` | patternn | `->` | exprn

matches the value of `expr` against the patterns `pattern`1 to `pattern`n. If the matching against `pattern`i succeeds, the associated expression `expr`i is evaluated, and its value becomes the value of the whole `match` expression. The evaluation of `expr`i 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.

Boolean operators

The expression `expr`1 `&&` `expr`2 evaluates to `true` if both `expr`1 and `expr`2 evaluate to `true`; otherwise, it evaluates to `false`. The first component, `expr`1, is evaluated first. The second component, `expr`2, is not evaluated if the first component evaluates to `false`. Hence, the expression `expr`1 `&&` `expr`2 behaves exactly as
`if` `expr`1 `then` `expr`2 `else` `false`.
The expression `expr`1 `||` `expr`2 evaluates to `true` if one of `expr`1 and `expr`2 evaluates to `true`; otherwise, it evaluates to `false`. The first component, `expr`1, is evaluated first. The second component, `expr`2, is not evaluated if the first component evaluates to `true`. Hence, the expression `expr`1 `||` `expr`2 behaves exactly as
`if` `expr`1 `then` `true` `else` `expr`2.
The boolean operator `&` is synonymous for `&&`. The boolean operator `or` is synonymous for `||`.

Loops

The expression `while` `expr`1 `do` `expr`2 `done` repeatedly evaluates `expr`2 while `expr`1 evaluates to `true`. The loop condition `expr`1 is evaluated and tested at the beginning of each iteration. The whole `while` ... `done` expression evaluates to the unit value `()`.
The expression `for` `name` `=` `expr`1 `to` `expr`2 `do` `expr`3 `done` first evaluates the expressions `expr`1 and `expr`2 (the boundaries) into integer values n and p. Then, the loop body `expr`3 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` `=` `expr`1 `downto` `expr`2 `do` `expr`3 `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 `()`.

Exception handling

The expression

`try` | expr
`with` | pattern1 | `->` | expr1
`|` | ...
`|` | patternn | `->` | exprn

evaluates 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 `pattern`1 to `pattern`n. If the matching against `pattern`i succeeds, the associated expression `expr`i is evaluated, and its value becomes the value of the whole `try` expression. The evaluation of `expr`i 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.

6.7.3 | Operations on data structures

Products

The expression `expr`1 `,` ... `,` `expr`n evaluates to the n-tuple of the values of expressions `expr`1 to `expr`n. The evaluation order for the subexpressions is not specified.

Variants

The expression `constr` `expr` evaluates to the variant value whose constructor is `constr`, and whose argument is the value of `expr`.
For lists, some syntactic sugar is provided. The expression `expr`1 `::` `expr`2 stands for the constructor `(` `::` `)` applied to the argument `(` `expr`1 `,` `expr`2 `)`, and therefore evaluates to the list whose head is the value of `expr`1 and whose tail is the value of `expr`2. The expression `[` `expr`1 `;` ... `;` `expr`n `]` is equivalent to `expr`1 `::` ... `::` `expr`n `::` `[]`, and therefore evaluates to the list whose elements are the values of `expr`1 to `expr`n.

Polymorphic variants

The expression ````tag-name` `expr` evaluates to the variant value whose tag is `tag-name`, and whose argument is the value of `expr`.

Records

The expression `{` `field`1 `=` `expr`1 `;` ... `;` `field`n `=` `expr`n `}` evaluates to the record value `{` `field`1 `=` `v`1 `;` ... `;` `field`n `=` `v`n `}`, where `v`i is the value of `expr`i for i = 1,... , n. The fields `field`1 to `field`n must all belong to the same record types; all fields belonging to this record type must appear exactly once in the record expression, though they can appear in any order. The order in which `expr`1 to `expr`n are evaluated is not specified.
The expression `{` `expr` `with` `field`1 `=` `expr`1 `;` ... `;` `field`n `=` `expr`n `}` builds a fresh record with fields `field`1 ... `field`n equal to `expr`1 ... `expr`n, and all other fields having the same value as in the record `expr`. In other terms, it returns a shallow copy of the record `expr`, except for the fields `field`1 ... `field`n, which are initialized to `expr`1 ... `expr`n.
The expression `expr`1 `.` `field` evaluates `expr`1 to a record value, and returns the value associated to `field` in this record value.
The expression `expr`1 `.` `field` `<-` `expr`2 evaluates `expr`1 to a record value, which is then modified in-place by replacing the value associated to `field` in this record by the value of `expr`2. This operation is permitted only if `field` has been declared `mutable` in the definition of the record type. The whole expression `expr`1 `.` `field` `<-` `expr`2 evaluates to the unit value `()`.

Arrays

The expression `[|` `expr`1 `;` ... `;` `expr`n `|]` evaluates to a n-element array, whose elements are initialized with the values of `expr`1 to `expr`n respectively. The order in which these expressions are evaluated is unspecified.
The expression `expr`1 `.(` `expr`2 `)` returns the value of element number `expr`2 in the array denoted by `expr`1. 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 `expr`1 `.(` `expr`2 `)` `<-` `expr`3 modifies in-place the array denoted by `expr`1, replacing element number `expr`2 by the value of `expr`3. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is `()`.

Strings

The expression `expr`1 `.[` `expr`2 `]` returns the value of character number `expr`2 in the string denoted by `expr`1. 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 `expr`1 `.[` `expr`2 `]` `<-` `expr`3 modifies in-place the string denoted by `expr`1, replacing character number `expr`2 by the value of `expr`3. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is `()`.

6.7.4 | Operators

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 `expr`1 `infix-symbol` `expr`2 is interpreted as the application `(` `infix-symbol` `)` `expr`1 `expr`2.
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 20 for more details). Their meaning may be changed at any time using `let` `(` `infix-op` `)` `name`1 `name`2 `=` ...

Operator | Initial meaning
`+` | Integer addition.
`-` (infix) | Integer subtraction.
`-` (prefix) | Integer negation.
`*` | Integer multiplication.
`/` | Integer division. Raise `Division_by_zero` if second argument is zero.
`mod` | Integer modulus. Raise `Division_by_zero` if second argument is zero.
`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''.

6.7.5 | Objects

Object creation

When `class-path` evaluates to a class body, `new` `class-path` evaluates to an object containing the instance variables and methods of this class.
When `class-path` evaluates to a class function, `new` `class-path` evaluates to a function expecting the same number of arguments and returning a new object of this class.

Message sending

The expression `expr` `#` `method-name` invokes the method `method-name` of the object denoted by `expr`.
If `method-name` is a polymorphic method, its type should be known at the invocation site. This is true for instance if `expr` is the name of a fresh object (`let` `ident` = `new` `class-path` ... ) or if there is a type constraint. Principality of the derivation can be checked in the `-principal` mode.

Accessing and modifying instance variables

The instance variables of a class are visible only in the body of the methods defined in the same class or a class that inherits from the class defining the instance variables. The expression `inst-var-name` evaluates to the value of the given instance variable. The expression `inst-var-name` `<-` `expr` assigns the value of `expr` to the instance variable `inst-var-name`, which must be mutable. The whole expression `inst-var-name` `<-` `expr` evaluates to `()`.

Coercion

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` `:` `typexpr`1 `:>` `typexpr`2 `)` coerces the expression `expr` from type `typexpr`1 to type `typexpr`2. The former operator will sometimes fail to coerce an expression `expr` from a type `t`1 to a type `t`2 even if type `t`1 is a subtype of type `t`2: in the current implementation it only expands two levels of type abbreviations containing objects and/or variants, keeping only recursion when it is explicit in the class type. In case of failure, 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.

Object duplication

An object can be duplicated using the library function `Oo.copy` (see Module `Oo`). 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.