## 6.7 Expressionsこのページは最後に更新されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。 last mod. 2008-09-20 (土) 08:02:10
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 ∣ object class-body end ∣ 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) –
## … lsl lsr asr right## … /… %… mod land lor lxor 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 : typexpr ). This constraint forces the type of expr to be compatible with typexpr. Parenthesized expressions can also contain coercions ( expr [: typexpr] :> typexpr) (see subsection 6.7.5 below). Function application Function application is denoted by juxtaposition of (possibly labeled) expressions. The expression expr argument1 … argumentn evaluates the expression expr and those appearing in argument1 to argumentn. The expression expr must evaluate to a functional value f, which is then applied to the values of argument1, …, argumentn. The order in which the expressions expr, argument1, …, argumentn 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 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: fun parameter1 … parametern -> expr This expression is equivalent to: fun parameter1 -> … fun parametern -> expr Functions of the form fun optlabel ( pattern = expr0 ) -> expr are equivalent to fun optlabel ident -> let pattern = match ident with Some ident -> ident | None -> expr0 in expr where ident is a fresh variable. When expr0 will be evaluated is left unspecified. After these two transformations, expressions are of the form fun [label1] pattern1 -> … fun [labeln] patternn -> expr If we ignore labels, which will only be meaningful at function application, this is equivalent to function pattern1 -> … function 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. 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 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. Local definitions The let and let rec constructs bind value names locally. The construct let pattern1 = expr1 and … and patternn = exprn in expr 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. An alternate syntax is provided to bind variables to functional values: instead of writing let ident = fun parameter1 … parameterm -> expr in a let expression, one may instead write let ident parameter1 … parameterm = expr Recursive definitions of names are introduced by let rec: let rec pattern1 = expr1 and … and patternn = exprn 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 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. 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: let rec name1 = fun … and … and namen = fun … in expr This defines name1 … namen 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 expr1 ; expr2 evaluates expr1 first, then expr2, and returns the value of expr2. Conditional 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 (). Case expression The expression match expr with pattern1 -> expr1 | … | patternn -> exprn matches 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. Boolean operators 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 expr1 then expr2 else false. The expression expr1 || 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 || expr2 behaves exactly as if expr1 then true else expr2. The boolean operator & is synonymous for &&. The boolean operator or is synonymous for ||. Loops 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 (). 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 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. 6.7.3 Operations on data structures Products 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. 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 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. 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 { field1 = expr1 ; … ; fieldn = exprn } evaluates to the record value { field1 = v1; …; fieldn = vn } where vi is the value of expri for i = 1,… , n. The fields field1 to fieldn 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 expr1 to exprn are evaluated is not specified. The expression { expr with field1 = expr1 ; … ; fieldn = exprn } builds a fresh record with fields field1 … fieldn equal to expr1 … exprn, 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 field1 … fieldn, which are initialized to expr1 … exprn. The expression expr1 . field evaluates expr1 to a record value, and returns the value associated to field in this record value. The expression expr1 . field <- expr2 evaluates expr1 to a record value, which is then modified in-place by replacing the value associated to field in this record by the value of expr2. This operation is permitted only if field has been declared mutable in the definition of the record type. The whole expression expr1 . field <- expr2 evaluates to the unit value (). Arrays 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 (). Strings 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 (). 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 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 20 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. 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.
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. Immediate object creation Creating directly an object through the object class-body end construct is operationally equivalent to defining locally a class class-name = object class-body end —see sections 6.9.2 and following for the syntax of class-body— and immediately creating a single object from it by new class-name. The typing of immediate objects is slightly different from explicitely defining a class in two respects. First, the inferred object type may contain free type variables. Second, since the class body of an immediate object will never be extended, its self type can be unified with a closed object type. 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 : 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 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. |