|
See also the following language extensions:first-class modules,overriding in open statements,syntax for Bigarray access,attributes,extension nodes andextended indexing operators.
The table below shows the relative precedences and associativity ofoperators and non-closed constructions. The constructions with higherprecedence come first. For infix and prefix symbols, we write“*…” to mean “any symbol starting with*”.
| Construction or operator | Associativity |
| prefix-symbol | – |
| . .( .[ .{ (see section 12.11) | – |
| #… | left |
| function application, constructor application, tagapplication,assert,lazy | left |
| - -. (prefix) | – |
| **… lsl lsr asr | right |
| *… /… %… mod land lor lxor | left |
| +… -… | left |
| :: | right |
| @… ^… | right |
| =… <… >… |… &… $… != | left |
| & && | right |
| or || | right |
| , | – |
| <- := | right |
| if | – |
| ; | right |
| let match fun function try | – |
It is simple to test or refresh one’s understanding:
An expression consisting in a constant evaluates to this constant. For example,3.14 or[||].
An expression consisting in an access path evaluates to the value bound tothis path in the current evaluation environment. The path canbe either a value name or an access path to a value component of a module.
The expressions(expr) andbeginexprend have the samevalue asexpr. The two constructs are semantically equivalent, but itis good style to usebegin …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:typexpr). This constraint forces the type ofexpr to becompatible withtypexpr.
Parenthesized expressions can also contain coercions(expr [:typexpr]:>typexpr) (seesubsection 11.7.7 below).
Function application is denoted by juxtaposition of (possibly labeled)expressions. The expressionexprargument1 …argumentnevaluates the expressionexpr and those appearing inargument1toargumentn. The expressionexpr must evaluate to afunctional valuef, which is then applied to the values ofargument1, …,argumentn.
The order in which the expressionsexpr,argument1, …,argumentn are evaluated is not specified.
Arguments and parameters are matched according to their respectivelabels. Argument order is irrelevant, except among arguments with thesame label, or no label.
If a parameter is specified as optional (label prefixed by?) in thetype ofexpr, the corresponding argument will be automaticallywrapped with the constructorSome, except if the argument itself isalso prefixed by?, in which case it is passed as is.
If a non-labeled argument is passed, and its corresponding parameteris preceded by one or several optional parameters, then theseparameters aredefaulted,i.e. the valueNone will bepassed for them.All other missing parameters (without corresponding argument), bothoptional and non-optional, will be kept, and the result of thefunction will still be a function of these missing parameters to thebody off.
In all cases but exact match of order and labels, without optionalparameters, the function type should be known at the applicationpoint. This can be ensured by adding a type constraint. Principalityof the derivation can be checked in the-principal mode.
As a special case, OCaml supportslabels-omitted full applications:if the function has a known arity, all the arguments are unlabeled,and their number matches the number of non-optional parameters, thenlabels are ignored and non-optional parameters are matched in theirdefinition order. Optional arguments are defaulted. This omission oflabels is discouraged and results in a warning, see13.5.1.
Two syntactic forms are provided to define functions. The first formis introduced by the keywordfunction:
|
This expression evaluates to a functional value with one argument.When this function is applied to a valuev, this value ismatched against each patternpattern1 topatternn.If one of these matchings succeeds, that is, if the valuevmatches the patternpatterni for somei,then the expressionexpri associated to the selected patternis evaluated, and its value becomes the value of the functionapplication. The evaluation ofexpri takes place in anenvironment enriched by the bindings performed during the matching.
If several patterns match the argumentv, the one that occursfirst in the function definition is selected. If none of the patternsmatches the argument, the exceptionMatch_failure is raised.
The other form of function definition is introduced by the keywordfun:
This expression is equivalent to:
An optional type constrainttypexpr can be added before-> to enforcethe type of the result to be compatible with the constrainttypexpr:
is equivalent to
Beware of the small syntactic difference between a type constraint onthe last parameter
and one on the result
The parameter patterns~lab and~(lab [:typ])are shorthands for respectively~lab:lab and~lab:(lab [:typ]), and similarly for their optionalcounterparts.
A function of the formfun?lab:(pattern=expr0)->expr is equivalent to
whereidentis a fresh variable, except that it is unspecified whenexpr0 is evaluated.
After these two transformations, expressions are of the form
If we ignore labels, which will only be meaningful at functionapplication, this is equivalent to
That is, thefun expression above evaluates to a curried functionwithn arguments: after applying this functionn times to thevaluesv1 …vn, the values will be matchedin parallel against the patternspattern1 …patternn.If the matching succeeds, the function returns the value ofexpr inan environment enriched by the bindings performed during the matchings.If the matching fails, the exceptionMatch_failure is raised.
The cases of a pattern matching (in thefunction,match andtry constructs) can include guard expressions, which arearbitrary boolean expressions that must evaluate totrue for thematch case to be selected. Guards occur just before the-> token andare introduced by thewhen keyword:
|
Matching proceeds as described before, except that if the valuematches some patternpatterni which has a guardcondi, then theexpressioncondi is evaluated (in an environment enriched by thebindings performed during matching). Ifcondi evaluates totrue,thenexpri is evaluated and its value returned as the result of thematching, as usual. But ifcondi evaluates tofalse, the matchingis resumed against the patterns followingpatterni.
Thelet andletrec constructs bind value names locally.The construct
evaluatesexpr1 …exprn in some unspecified order and matchestheir values against the patternspattern1 …patternn. If thematchings succeed,expr is evaluated in the environment enriched bythe bindings performed during matching, and the value ofexpr isreturned as the value of the wholelet expression. If one of thematchings fails, the exceptionMatch_failure is raised.
An alternate syntax is provided to bind variables to functionalvalues: instead of writing
in alet expression, one may instead write
Recursive definitions of names are introduced byletrec:
The only difference with thelet construct described above isthat the bindings of names to values performed by thepattern-matching are considered already performed when the expressionsexpr1 toexprn are evaluated. That is, the expressionsexpr1toexprn can reference identifiers that are bound by one of thepatternspattern1, …,patternn, and expect them to have thesame value as inexpr, the body of theletrec construct.
The recursive definition is guaranteed to behave as described above ifthe expressionsexpr1 toexprn are function definitions(fun … orfunction …), and the patternspattern1…patternn are just value names, as in:
This definesname1 …namen as mutually recursive functionslocal toexpr.
The behavior of other forms ofletrec definitions isimplementation-dependent. The current implementation also supportsa certain class of recursive definitions of non-functional values,as explained in section 12.1.
(Introduced in OCaml 4.04)
It is possible to define local exceptions in expressions:letexceptionconstr-declinexpr .
The syntactic scope of the exception constructor is the innerexpression, but nothing prevents exception values created with thisconstructor from escaping this scope. Two executions of the definitionabove result in two incompatible exception constructors (as for anyexception definition). For instance:
(Introduced in OCaml 3.12)
Polymorphic type annotations inlet-definitions behave in a waysimilar to polymorphic methods:
These annotations explicitly require the defined value to be polymorphic,and allow one to use this polymorphism in recursive occurrences(when usingletrec). Note however that this is a normal polymorphictype, unifiable with any instance of itself.
The expressionexpr1;expr2 evaluatesexpr1 first, thenexpr2, and returns the value ofexpr2.
The expressionifexpr1thenexpr2elseexpr3 evaluates tothe value ofexpr2 ifexpr1 evaluates to the booleantrue,and to the value ofexpr3 ifexpr1 evaluates to the booleanfalse.
Theelseexpr3 part can be omitted, in which case it defaults toelse().
The expression
|
matches the value ofexpr against the patternspattern1 topatternn. If the matching againstpatterni succeeds, theassociated expressionexpri is evaluated, and its value becomes thevalue of the wholematch expression. The evaluation ofexpri takes place in an environment enriched by the bindingsperformed during matching. If several patterns match the value ofexpr, the one that occurs first in thematch expression isselected.
If none of the patterns match the value ofexpr, theexceptionMatch_failure is raised.
The expressionexpr1&&expr2 evaluates totrue if bothexpr1 andexpr2 evaluate totrue; otherwise, it evaluates tofalse. The first component,expr1, is evaluated first. Thesecond component,expr2, is not evaluated if the first componentevaluates tofalse. Hence, the expressionexpr1&&expr2 behavesexactly as
The expressionexpr1||expr2 evaluates totrue if one ofthe expressionsexpr1 andexpr2 evaluates totrue; otherwise, it evaluates tofalse. The first component,expr1, is evaluated first. Thesecond component,expr2, is not evaluated if the first componentevaluates totrue. Hence, the expressionexpr1||expr2 behavesexactly as
The boolean operators& andor are deprecated synonyms for(respectively)&& and||.
The expressionwhileexpr1doexpr2done repeatedlyevaluatesexpr2 whileexpr1 evaluates totrue. The loopconditionexpr1 is evaluated and tested at the beginning of eachiteration. The wholewhile …done expression evaluates tothe unit value().
As a special case,whiletruedoexprdone is given apolymorphic type, allowing it to be used in place of any expression(for example as a branch of any pattern-matching).
The expressionforname=expr1toexpr2doexpr3donefirst evaluates the expressionsexpr1 andexpr2 (the boundaries)into integer valuesn andp. Then, the loop bodyexpr3 isrepeatedly evaluated in an environment wherename is successivelybound to the valuesn,n+1, …,p−1,p.The loop body is never evaluated ifn >p.
The expressionforname=expr1downtoexpr2doexpr3doneevaluates similarly, except thatname is successively bound to the valuesn,n−1, …,p+1,p.The loop body is never evaluated ifn <p.
In both cases, the wholefor expression evaluates to the unitvalue().
The expression
|
evaluates the expressionexpr and returns its value if theevaluation ofexpr does not raise any exception. If the evaluationofexpr raises an exception, the exception value is matched againstthe patternspattern1 topatternn. If the matching againstpatterni succeeds, the associated expressionexpri is evaluated,and its value becomes the value of the wholetry expression. Theevaluation ofexpri takes place in an environment enriched by thebindings performed during matching. If several patterns match the value ofexpr, the one that occurs first in thetry expression isselected. If none of the patterns matches the value ofexpr, theexception value is raised again, thereby transparently “passingthrough” thetry construct.
The expressionexpr1, …,exprn evaluates to then-tuple of the values of expressionsexpr1 toexprn. Theevaluation order of the subexpressions is not specified.
The expressionconstrexpr evaluates to the unary variant valuewhose constructor isconstr, and whose argument is the value ofexpr. Similarly, the expressionconstr(expr1, …,exprn) evaluates to the n-ary variant value whose constructor isconstr and whose arguments are the values ofexpr1, …,exprn.
The expressionconstr(expr1, …,exprn) evaluates to thevariant value whose constructor isconstr, and whose arguments arethe values ofexpr1 …exprn.
For lists, some syntactic sugar is provided. The expressionexpr1::expr2 stands for the constructor(::) applied to the arguments(expr1,expr2), and thereforeevaluates to the list whose head is the value ofexpr1 and whose tailis the value ofexpr2. The expression[expr1; …;exprn] is equivalent toexpr1:: …::exprn::[], and therefore evaluates to the list whose elements are thevalues ofexpr1 toexprn.
The expression`tag-nameexpr evaluates to the polymorphic variantvalue whose tag istag-name, and whose argument is the value ofexpr.
The expression{field1 [=expr1]; …;fieldn [=exprn]} evaluates to the record value{field1 =v1; …;fieldn =vn }wherevi is the value ofexpri fori = 1,… ,n.A single identifierfieldk stands forfieldk=fieldk,and a qualified identifiermodule-path.fieldk stands formodule-path.fieldk=fieldk.The fieldsfield1 tofieldn must all belong to the same recordtype; each field of this record type must appear exactlyonce in the record expression, though they can appear in anyorder. The order in whichexpr1 toexprn are evaluated is notspecified. Optional type constraints can be added after each field{field1:typexpr1=expr1;…;fieldn:typexprn=exprn}to force the type offieldk to be compatible withtypexprk.
The expression{exprwithfield1 [=expr1]; …;fieldn [=exprn]}builds a fresh record with fieldsfield1 …fieldn equal toexpr1 …exprn, and all other fields having the same value asin the recordexpr. In other terms, it returns a shallow copy ofthe recordexpr, except for the fieldsfield1 …fieldn,which are initialized toexpr1 …exprn. As previously,single identifierfieldk stands forfieldk=fieldk,a qualified identifiermodule-path.fieldk stands formodule-path.fieldk=fieldk and it ispossible to add an optional type constraint on each field being updatedwith{exprwithfield1:typexpr1=expr1; …;fieldn:typexprn=exprn}.
The expressionexpr1.field evaluatesexpr1 to a recordvalue, and returns the value associated tofield in this recordvalue.
The expressionexpr1.field<-expr2 evaluatesexpr1 to a recordvalue, which is then modified in-place by replacing the valueassociated tofield in this record by the value ofexpr2. This operation is permitted only iffield has beendeclaredmutable in the definition of the record type. The wholeexpressionexpr1.field<-expr2 evaluates to the unit value().
The expression[|expr1; …;exprn|] evaluates toan-element array, whose elements are initialized with the values ofexpr1 toexprn respectively. The order in which theseexpressions are evaluated is unspecified.
The expressionexpr1.(expr2) returns the value of elementnumberexpr2 in the array denoted byexpr1. The first elementhas number 0; the last element has numbern−1, wheren is thesize of the array. The exceptionInvalid_argument is raised if theaccess is out of bounds.
The expressionexpr1.(expr2)<-expr3 modifies in-placethe array denoted byexpr1, replacing element numberexpr2 bythe value ofexpr3. The exceptionInvalid_argument is raised ifthe access is out of bounds. The value of the whole expression is().
The expressionexpr1.[expr2] returns the value of characternumberexpr2 in the string denoted byexpr1. The first characterhas number 0; the last character has numbern−1, wheren is thelength of the string. The exceptionInvalid_argument is raised if theaccess is out of bounds.
The expressionexpr1.[expr2]<-expr3 modifies in-placethe string denoted byexpr1, replacing character numberexpr2 bythe value ofexpr3. The exceptionInvalid_argument is raised ifthe access is out of bounds. The value of the whole expression is().Note: this possibility is offered only for backwardcompatibility with older versions of OCaml and will be removed in afuture version. New code should use byte sequences and theBytes.setfunction.
Symbols from the classinfix-symbol, as well as the keywords*,+,-,-.,=,!=,<,>,or,||,&,&&,:=,mod,land,lor,lxor,lsl,lsr,andasr can appear in infix position (between twoexpressions). Symbols from the classprefix-symbol, as well asthe keywords- and-.can appear in prefix position (in front of an expression).
Infix and prefix symbols do not have a fixed meaning: they are simplyinterpreted as applications of functions bound to the namescorresponding to the symbols. The expressionprefix-symbolexpr isinterpreted as the application(prefix-symbol)expr. Similarly, the expressionexpr1infix-symbolexpr2 isinterpreted as the application(infix-symbol)expr1expr2.
The table below lists the symbols defined in the initial environmentand their initial meaning. (See the description of the corelibrary moduleStdlib in chapter 28 for moredetails). Their meaning may be changed at any time usinglet(infix-op)name1name2= …
Note: the operators&&,||, and~- are handled speciallyand it is not advisable to change their meaning.
The keywords- and-. can appear both as infix andprefix operators. When they appear as prefix operators, they areinterpreted respectively as the functions(~-) and(~-.).
| Operator | Initial meaning |
| + | Integer addition. |
| - (infix) | Integer subtraction. |
| ~- - (prefix) | Integer negation. |
| * | Integer multiplication. |
| / | Integer division.RaiseDivision_by_zero if second argument is zero. |
| mod | Integer modulus. RaiseDivision_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 currentcontents of a reference). |
| := | Reference assignment (update thereference given as first argument with the value of the secondargument). |
| = | 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”. |
| && & | Boolean conjunction. |
| || or | Boolean disjunction. |
Whenclass-path evaluates to a class body,newclass-pathevaluates to a new object containing the instance variables andmethods of this class.
Whenclass-path evaluates to a class function,newclass-pathevaluates to a function expecting the same number of arguments andreturning a new object of this class.
Creating directly an object through theobjectclass-bodyendconstruct is operationally equivalent to defining locally aclassclass-name=objectclass-bodyend —see sections11.9.2 and following for the syntax ofclass-body—and immediately creating a single object from it bynewclass-name.
The typing of immediate objects is slightly different from explicitlydefining a class in two respects. First, the inferred object type maycontain free type variables. Second, since the class body of animmediate object will never be extended, its self type can be unifiedwith a closed object type.
The expressionexpr#method-name invokes the methodmethod-name of the object denoted byexpr.
Ifmethod-name is a polymorphic method, its type should be known atthe invocation site. This is true for instance ifexpr is the nameof a fresh object (letident =newclass-path … ) or ifthere is a type constraint. Principality of the derivation can bechecked in the-principal mode.
The instance variables of a class are visible only in the body of themethods defined in the same class or a class that inherits from theclass defining the instance variables. The expressioninst-var-nameevaluates to the value of the given instance variable. The expressioninst-var-name<-expr assigns the value ofexpr to the instancevariableinst-var-name, which must be mutable. The whole expressioninst-var-name<-expr evaluates to().
An object can be duplicated using the library functionOo.copy(see moduleOo). Inside a method, the expression{< [inst-var-name [=expr] {;inst-var-name [=expr] }]>}returns a copy of self with the given instance variables replaced bythe values of the associated expressions. A single instance variablenameid stands forid=id. Other instance variables have the samevalue in the returned object as in self.
Expressions whose type contains object or polymorphic variant typescan be explicitly coerced (weakened) to a supertype.The expression(expr:>typexpr) coerces the expressionexprto typetypexpr.The expression(expr:typexpr1:>typexpr2) coerces theexpressionexpr from typetypexpr1 to typetypexpr2.
The former operator will sometimes fail to coerce an expressionexprfrom a typetyp1 to a typetyp2even if typetyp1 is a subtype of typetyp2: in the current implementation it only expands two levels oftype abbreviations containing objects and/or polymorphic variants,keeping only recursion when it is explicit in the class type (for objects).As an exception to the above algorithm, if both the inferred type ofexprandtyp are ground (i.e. do not contain type variables), theformer operator behaves as the latter one, taking the inferred type ofexpr astyp1. In case of failure with the former operator,the latter one should be used.
It is only possible to coerce an expressionexpr from typetyp1 to typetyp2, if the type ofexpr is an instance oftyp1 (like for a type annotation), andtyp1 is a subtypeoftyp2. The type of the coerced expression is aninstance oftyp2. If the types contain variables,they may be instantiated by the subtyping algorithm, but this is onlydone after determining whethertyp1 is a potential subtype oftyp2. This means that typing may fail during this latterunification step, even if some instance oftyp1 is a subtype ofsome instance oftyp2.In the following paragraphs we describe the subtyping relation used.
A fixed object type admits as subtype any object type that includes allits methods. The types of the methods shall be subtypes of those inthe supertype. Namely,
is a supertype of
which may contain an ellipsis.. if everytypi is a supertype ofthe correspondingtyp′i.
A monomorphic method type can be a supertype of a polymorphic methodtype. Namely, iftyp is an instance oftyp′, then'a1…'an.typ′ is a subtype oftyp.
Inside a class definition, newly defined types are not available forsubtyping, as the type abbreviations are not yet completelydefined. There is an exception for coercingself to the (exact)type of its class: this is allowed if the type ofself does notappear in a contravariant position in the class type,i.e. ifthere are no binary methods.
A polymorphic variant typetyp is a subtype of another polymorphicvariant typetyp′ if the upper bound oftyp (i.e. themaximum set of constructors that may appear in an instance oftyp)is included in the lower bound oftyp′, and the types of argumentsfor the constructors oftyp are subtypes of those intyp′. Namely,
which may be a shrinkable type, is a subtype of
which may be an extensible type, if everytypi is a subtype oftyp′i.
Other types do not introduce new subtyping, but they may propagate thesubtyping of their arguments. For instance,typ1*typ2 is asubtype oftyp′1*typ′2 whentyp1 andtyp2 arerespectively subtypes oftyp′1 andtyp′2.For function types, the relation is more subtle:typ1->typ2 is a subtype oftyp′1 ->typ′2iftyp1 is a supertype oftyp′1 andtyp2 is asubtype oftyp′2. For this reason, function types are covariant intheir second argument (like tuples), but contravariant in their firstargument. Mutable types, likearray orref are neither covariantnor contravariant, they are nonvariant, that is they do not propagatesubtyping.
For user-defined types, the variance is automatically inferred: aparameter is covariant if it has only covariant occurrences,contravariant if it has only contravariant occurrences,variance-free if it has no occurrences, and nonvariant otherwise.A variance-free parameter may change freely through subtyping, it doesnot have to be a subtype or a supertype.For abstract and private types, the variance must be given explicitly(see section 11.8.1),otherwise the default is nonvariant. This is also the case forconstrained arguments in type definitions.
OCaml supports theassert construct to check debugging assertions.The expressionassertexpr evaluates the expressionexpr andreturns() ifexpr evaluates totrue. If it evaluates tofalse the exceptionAssert_failure is raised with the source file name and thelocation ofexpr as arguments. Assertionchecking can be turned off with the-noassert compiler option. Inthis case,expr is not evaluated at all.
As a special case,assert false is reduced toraise(Assert_failure ...), which gives it a polymorphictype. This means that it can be used in place of any expression (forexample as a branch of any pattern-matching). It also means thattheassert false “assertions” cannot be turned off by the-noassert option.
The expressionlazyexpr returns a valuev of typeLazy.t thatencapsulates the computation ofexpr. The argumentexpr is notevaluated at this point in the program. Instead, its evaluation willbe performed the first time the functionLazy.force is applied to the valuev, returning the actual value ofexpr. Subsequent applicationsofLazy.force tov do not evaluateexpr again. ApplicationsofLazy.force may be implicit through pattern matching (see 11.6).
The expressionletmodulemodule-name=module-exprinexprlocally binds the module expressionmodule-expr to the identifiermodule-name during the evaluation of the expressionexpr.It then returns the value ofexpr. For example:
The expressionsletopenmodule-pathinexpr andmodule-path.(expr) are strictly equivalent. Theseconstructions locally open the module referred to by the module pathmodule-path in the respective scope of the expressionexpr.
When the body of a local open expression is delimited by[],[||], or{}, the parentheses can be omitted.For expression, parentheses can also be omitted for{<>}.For example,module-path.[expr] is equivalent tomodule-path.([expr]), andmodule-path.[|expr|] isequivalent tomodule-path.([|expr|]).