下の表は演算子と閉じていない構文の相対的な優先順位と結合性の表で、それぞれ優先順位の高い構文から順に並んでいます。
前置演算子と中置演算子の部分の「*...
」は「*
で始まるシンボル」を表します。
構文または演算子 | 結合性 |
---|---|
前置演算子 | - |
. .( .[ |
- |
関数適用、構成子適用、 assert 、 lazy |
左 |
- -. (前置) | - |
**… lsl lsr asr |
右 |
*… /… %… mod land lor lxor |
左 |
+… -… |
左 |
:: |
右 |
@… ^… |
右 |
=…
<… >…
|… &… $… |
左 |
& && |
右 |
or || | 右 |
, | - |
<- := | 右 |
if | - |
; | 右 |
let match fun function try | - |
constant に含まれる式はその定数に評価されます。
value-path に含まれる式は現在の評価環境の中でこのパスに束縛された値に評価されます。 パスは値の名前かモジュールの値要素へのアクセスパスです。
式
( expr )
と式
begin expr end
は
expr
としては同じ値です。
どちらの構文も意味上は等価ですが、制御構造の中では
if … then begin … ; … end else begin … ; … end
と、 begin
を使い、
それ以外で式をグループ化したいときには end(
を使うのがよいスタイルです。
)
括弧付きの式には
( expr : typexpr )
のように型制約をつけることができます。
これにより、 expr が typexpr に適合するように制約をつけられます。
括弧付きの式には
( expr : typexpr :> typexpr )
のように型変換をつけられます( 6.7.6 節「型変換 」 を参照してください)。
関数適用は(ラベルつきの)式を並べることで表されます。
式
expr argument1 ... argumentn
は式 expr と
argument1 から argumentn
中の式を評価します。
式 expr は関数値 f
に評価されなければなりません。
その値が argument1 から argumentn
の値に適用されます。
式 expr、 argument1、 argumentn
の評価順序は規定されていません。
実引数と仮引数はそれぞれのラベルについて対応していなければなりません。 同一のラベルのついた引数同士や、ラベルのない引数同士以外では引数の順序に意味はありません。
expr
の型で仮引数が省略可能だとされている場合(ラベルの前に ?
がついている場合)、引数自体にも ?
が前置されていなければ、対応する仮引数は自動的に Some
構成子でラップされます。
引数自体に ?
が前置されている場合には、引数がそのまま渡されます。
ラベルなしの引数が渡されたとき、それに対応する仮引き数の前にひとつ以上の省略可能な仮引数があると、これらの省略可能引数にはデフォルト値、すなわち None
が渡されます。
その他の指定されなかった(対応する引数のなかった)仮引数は、省略可能なものもそうでないものも、そのまま保持され、関数の戻り値は指定されなかった仮引数から f
の本体への関数になります。
特別な場合として、関数の仮引数の個数がわかっていて、かつ実引数にはすべてラベルがついていず、さらに実引数の個数が省略不可能な仮引数の個数と一致していた場合には、ラベルを無視し、実引数を省略不可能な引数に定義時の順番で対応づけます。 このとき省略可能引数にはデフォルト値が渡されます。
引数の順序とラベルが完全に一致する場合を除き、省略可能引数が存在しない場合は、常に関数の型は適用の時点で既知でなければなりません。
型制約を追加すればこれを保証することができます。
導出される型が一意であることは -principal
モードで検査することができます。
関数定義のための構文形式はふたつあります。
ひとつ目は予約語 function
で始まるものです。
この式は一引数の関数値に評価されます。
この関数が値 v
に適用されると、その値を
pattern1 から patternn
までのパターンとパターンマッチします。
これらのうちひとつが成功した場合、つまり、値 v
が何らかの i
について patterni
とマッチしたとき、選択されたパターンと対応づけられた式
expri
が評価され、その値が関数適用の値になります。
expri
はパターンマッチにより生成された束縛を加えた環境で評価されます。
引数 v
に対して複数のパターンが一致する場合、関数定義の中で最初に現れたものが選択されます。
引数に一致するパターンがない場合には、 Match_failure
例外が発生します。
もうひとつの形式は予約語 fun
を使うものです。
fun parameter1 parametern
-> expr
この式は次のものと等価です。
fun parameter1 -> fun parametern
-> expr
パラメータパターン ~var
と ~(var typexpr )
はそれぞれ : ~var:var
や ~var:(var typexpr )
の略記法です。省略可能引数にも同様の略記法があります。
:
fun ? label ( pattern = expr0 ) -> expr
の形式の関数は次のものと等価です。
fun ? label ident -> let pattern = match ident with Some ident -> ident | None -> expr0 in expr
ここで ident は新しい変数です。
このような変換を行なうと、式は次のような形式になります。
fun label1 pattern1 -> fun labeln
patternn
-> expr
ラベルを無視すればこれは次と等価です(ラベルは関数適用時にだけ意味を持ちます)。
function pattern1 -> function patternn
-> expr
すなわち、上の fun
式は n
引数のカリー化関数に評価されます。
この関数に値 v1
... v
を m
n
回適用すると、 v1
... v
はパターン pattern1 ... patternm
n
と並行にパターンマッチされます。
パターンマッチが成功した場合、 expr をパターンマッチによって生成された束縛を加えた環境で評価します。
パターンマッチに失敗した場合には Match_failure
例外が発生します。
(function
、 fun
、 match
、 try
構文中の)パターンマッチの各分岐にはガード式をつけることができます。ガード式は真理値を返す任意の式で、その分岐が選択される場合には true
に評価されます。
ガードは ->
の前に書き、予約語 when
で始まります。
function parameter1 when expr1 | | parametern
when exprn
パターンマッチは先に述べたように行なわれますが、値がガード cond
を持つパターン patterni
i
にマッチした場合、式
cond
が(パターンマッチにより生成された束縛を加えた環境で)評価されます。
i
cond
が i
true
に評価された場合には、通常と同じように
expri
が評価され、その値がパターンマッチの値として返されます。
cond
が i
false
に評価された場合には、
patterni
に続くパターンのパターンマッチを再開します。
let
構文と let rec
は名前を局所的に束縛します。
let pattern1 = expr1 and and patternn
= exprn
in expr
は、 expr1 exprn
が何らかの順序で評価されは、その値を pattern1 ... patternn
とマッチさせます。
パターンマッチに成功した場合には、パターンマッチにより生成された束縛を加えた環境で expr が評価され、 expr の値が let
式全体の値として返されます。
パターンマッチのうちひとつでも失敗したものがあれば、 Match_failure
例外が発生します。
変数を関数値に束縛するための特別の構文もあります。
let ident = fun parameter1 parameterm
-> expr
と書く代わりに次のように書きます。
let ident parameter1 parameterm
= expr
let rec
を使うと名前を再帰的に定義することができます。
上で述べた let
構文との違いは、パターンマッチによる名前の束縛が式
expr1 から exprn
が評価されるときに、既に確立されていると考えるということだけです。
つまり、
expr1 から exprn
では
pattern1 から patternn
で束縛された識別子を参照することができ、それらが
let rec
構文の本体の
expr 内と同じ値であると期待することができます。
下に示すように、
expr1 から exprn
が関数定義(fun
または function
)であり、
pattern1 から patternn
が単なる変数名であれば、再帰定義は上で述べたように振る舞うことが保証されます。
ここでは、
name1 から namen
を expr に局所的な相互再帰関数として定義しています。
他の形式 let rec
定義の振舞いは実装系依存です。
7.3 節「値の再帰的定義」 で述べるように、現在の実装では特定のクラスの値の再帰定義もサポートしています。
if expr1 then expr2 else expr3
は
expr1 が真理値の true
に評価された場合には
expr2 の値に評価され、
false
に評価された場合には
expr3 の値に評価されます。
else
expr3 の部分は省略することができ、その場合は
else ()
になります。
match expr with pattern1 -> expr1 | | patternn
-> exprn
は expr の値を
pattern1 から
patternn
にマッチさせます。
patterni
へのパターンマッチが成功した場合、対応する式
expri
が評価され、その値が match
式全体の値になります。
expri
はパターンマッチによって生成された束縛を加えた環境で評価されます。
expr の値に対して複数のパターンがマッチする場合、 match
式に最初に現れたものが選択されます。
マッチするものがなかった場合には Match_failure
例外が発生します。
expr1 && expr2
は
expr1
と
expr2
の両方が true
に評価されたとき true
に評価され、そうでなければ false
に評価されます。
最初の要素
expr1
が先に評価されます。
次の要素
expr2
は最初の要素が false
に評価された場合には評価されません。
したがって、
expr1 && expr2 振舞いは次の式とまったく同じです。
expr1 || expr2
は
expr1
と
expr2
のいずれかが true
に評価されたとき true
に評価され、そうでなければ false
に評価されます。
最初の要素
expr1
が先に評価されます。
次の要素
expr2
は最初の要素が true
に評価された場合には評価されません。
したがって、
expr1 || expr2
振舞いは次の式とまったく同じです。
if expr1 then true else expr2
論理演算子 & は && と同義で、 or は || と同義です。
while expr1 do expr2 done
は expr1 が true
に評価される間、繰り返し
expr2 を評価します。
ループ条件 expr1 は各繰り返しの最初に評価され検査されます。
while
式全体はユニット値 done()
に評価されます。
式
for name = expr1 to expr2 do expr3 done
は、まず式 expr1 と expr2 (境界)を整数値 n
と p
に評価します。
次にループの本体 expr3が、 name が次々と n
、n
+ 1、p
- 1、 p
に束縛された環境で繰り返し評価されます。
n
> p
であればループ本体は一度も評価されません。
for name = expr1 downto expr2 do expr3 done
も同じように評価されますが、 name は
n
、 n
- 1、 ...、 p
+ 1、 p
に束縛されて行きます。
n
> p
であればループ本体は一度も評価されません。
どちらの場合も、 for
式全体はユニット値 ()
に評価されます。
try expr with pattern1 -> expr1 | | patternn
-> exprn
は式 expr を評価し、例外が発生しなければその値を返します。
例外が発生した場合、例外の値が pattern1 から patternn
とパターンマッチされます。
patterni
とマッチした場合には、その対応する expri
が評価され、その値が try
式全体の値になります。
expri
の評価は、パターンマッチにより拡張された環境で行なわれます。
複数のパターンがマッチする場合、最初のものが選択されます。
マッチするものがない場合、その例外値を再送出します。
つまり、 try
構文は透過的に「素通り」されるのです。
constr expr は、構成子が constr で、引数が expr の値となるバリアントに評価されます。
リストには一種の糖衣構文が用意されています。
expr1 :: expr2
は、構成子 ( :: )
を引数 (expr1, expr2)
に適用したものを意味し、頭部が expr1、尾部が expr2 であるリストに評価されます。
[expr1; ; expr
は n
]expr1 :: :: expr
と等価で、 expr1 から exprn
:: []n
を要素とするリストに評価されます。
{ field1 = expr1; ; field
はレコード値 n
= exprn
}{ field1 =
に評価されます。
ここで、 v1
; ; fieldn
= v
}n
v
は i
i
= 1, ..., n
について expri
の値です。
field1 から fieldn
はすべて同一のレコード型に属していなければなりません。
レコード式にはこのレコード型に属するフィールドすべてが丁度一回ずつ現れなければなりませんが、順番はどのようであってもかまいません。
expr1 から exprn
の評価順序は規定されていません。
{ expr with field1 = expr1; ; field
は field1 から fieldn
= exprn
}n
が expr1 から exprn
に等しく、それ以外のフィールドはレコード expr と同じ値を持つ、新たなレコードを構成します。
別の言い方をすれば、 field1 から fieldn
を expr1 から exprn
に初期化し、それ以外のフィールドは expr を浅くコピーしたレコードを返します。
expr1.field
は expr1 がレコード値に評価され、その field に対応づけられた値が返ります。
expr1.field <- expr2
は expr1 がレコード値に評価され、そのレコードの field に対応づけられた値をその場で expr2 の値に修正します。
この操作は、このレコード型の定義で field が mutable と宣言されていた場合にだけ許されます。
式全体はユニット値 () に評価されます。
[| expr1; ; expr
は n
|]n
要素の配列に評価され、各要素は順に expr1 から exprn
に初期化されます。
これらの式の評価順序は規定されていません。
expr1.(expr2)
は expr1 の表す配列の expr2 番目の要素の値を返します。
配列の要素を n
としたとき、最初の要素は 0 番目で、最後の要素は n
- 1 番目になります。
領域外にアクセスした場合には Invalid_argument
例外が発生します。
expr1.(expr2) <- expr3
は、 expr1 の表す配列の expr2 番目の要素を expr3 の値で置き換えます。
領域外にアクセスした場合には Invalid_argument
例外が発生します。
式全体の値は () になります。
infix-symbol に属するシンボルは、予約語 *
、 =
、 or
、 &
と同じく式の間に中置することができます。
prefix-symbol に属するシンボルは式に前置することができます。
前置シンボルと中置シンボルには固定された意味はなく、単純に、そのシンボルに対応する名前に束縛された関数の適用と解釈されます。
式 prefix-symbol expr は ( prefix-symbol ) expr
という適用と解釈されます。
同様に、 expr1 infix-symbol expr2 は ( infix-symbol )
expr1 expr2 という適用と解釈されます。
下の表に初期環境で定義されているシンボルとその意味を示します(詳細は 19 章「コアライブラリ」のコアライブラリモジュール Pervasive
の説明を読んでください)。
これらの意味は let ( infix-op ) name1 name2 =
としていつでも変更することができます。
演算子 | 意味 |
---|---|
+ | 整数の足し算 |
- | (中置)整数の引き算 |
- | (前置)整数の符号反転 |
* | 整数の掛け算 |
/ | 整数の割り算。第二引数が 0 のときは Division_by_zero 例外が発生する |
mod | 整数の法。第二引数が 0 のときは Division_by_zero 例外が発生する |
land | 整数のビットごとの論理積 |
lor | 整数のビットごとの論理和 |
lxor | 整数のビットごとの排他的論理和 |
lsl | 整数のビットごとの左論理シフト |
lsr | 整数のビットごとの右論理シフト |
asr | 整数のビットごとの右算術シフト |
+. | 浮動小数点数の足し算 |
-. | (中置)浮動小数点数の引き算 |
-. | (前置)浮動小数点数の符号反転 |
*. | 浮動小数点数の掛け算 |
/. | 浮動小数点数の割り算 |
** | 浮動小数点数の累乗 |
@ | リストの連結 |
^ | 文字列の連結 |
! | 参照外し(参照の現在の内容を返す) |
:= | 参照への代入(第一引数として与えられた参照を第二引数の値で更新する) |
= | 構造的等価性のテスト |
<> | 構造的不等性のテスト |
== | 物理的等価性のテスト |
!= | 物理的不等性のテスト |
< | 「小なり」テスト |
<= | 「小なりイコール」テスト |
> | 「大なり」テスト |
>= | 「大なりイコール」テスト |
class-path がクラスの本体に評価されるとき、 new class-path
はこのクラスのインスタンス変数とメソッドを格納したオブジェクトに評価されます。
class-path がクラス関数に評価されるときには、 new class-path
はクラス関数と同一個数の引数を期待し、このクラスのオブジェクトを返す関数に評価されます。
object class-body end
として直接オブジェクトを生成するのは、 class class-name = object class-body end
として局所的にクラスを定義し(クラス本体 の class-body の構文参照)、即座にそのクラスに対して new class-name
として単一のオブジェクトを生成するのと、操作の上では等価です。
直接生成されたオブジェクトの型づけには定義済みのクラスのインスタンスを生成した場合と異なる点がふたつあります。 まずひとつには、推論された型に自由な型変数が含まれることがあります。 もうひとつには、直接生成されたオブジェクトのクラス本体は拡張されることがないので、そのオブジェクト自身の型は閉じたオブジェクト型に単一化することができます。
expr#method-name
は expr の表すオブジェクトのメソッド method-name を起動します。
method-name が多相メソッドであった場合、メソッドの型は起動する箇所で既知でなければなりません。
expr が新しいオブジェクト(let ident = new class-path
)の名前であるか、型制約がある場合にはこれは成り立ちます。
型導出の一意性は -principal
モードでチェックすることができます。
クラスのインスタンス変数は、インスタンス変数を定義したクラスと同一のクラスで定義されたメソッドやインスタンス変数を定義したクラスを継承したクラス内から参照できます。
inst-var-name は与えられたインスタンス変数の値に評価されます。
inst-var-name <- expr
は expr の値をインスタンス変数 inst-var-name に代入します。
このインスタンス変数は mutable でなければなりません。
代入式全体は () に評価されます。
ライブラリ関数 Oo.copy
(Oo
モジュール参照)を使うとオブジェクトを複製することができます。
メソッド中で、 {< inst-var-name = expr ; inst-var-name = expr >}
とすると、指定したインスタンス変数が対応する式の値で置き換えられた自身のコピーが返ります。
戻り値のオブジェクトのインスタンス変数うち指定されなかったものはコピー元と同じ値になります。
オブジェクトの型は上位型に変換する(弱める)ことができます。
( expr :> typexpr)
は式 expr の型を typexpr に変換します。
( expr : typexpr1 :> typexpr2)
は expr の型を typexpr1 から typexpr2 に変換します。
前者では expr の型を t1
を t2
に変換するとき、 t1
が t2
の部分型であっても型変換に失敗することがあります。
現在の実装ではオブジェクトや多相バリアントを含む型略記は二段階しか展開せず、再帰性はクラス型で明示されているものだけ管理されます。
失敗した場合には後者の形式を使わなければなりません。
クラス定義中で、そのクラスの定義する型への変換は恒等関数になります。 これは、この型略記に対応するものがまだ完全には定義されていないからです。