letによる束縛
letは、識別子を値(value)に束縛(bind)するための構文に用いるキーワードです。
束縛(binding)というのは、名前と定義を関連付けることを意味します
識別子をある値に束縛しておくと、
次からはその識別子で、値を参照することができます。
見慣れない用語が多く出てきていますが、
つまり、色々なものに名前をつけておいて
後で利用するのにletキーワードを使います。
インタプリタfsiを起動して、let a = 1;;と入力すると
サンプルコード
> let a = 1;;
val a : int
このように表示されます。
これは識別子aをint型の1という値へ
束縛(bind)していることを表しています。
するとaという識別子で今の値を参照できます。
値の参照
> a;;
val it : int = 1
> a+10;; //aを使った計算
val it : int = 11
letの構文
let ...の形で使える構文には
A.モジュールに値を定義する方法(10 top-level let。上の例)
B.特定の範囲内でのみ識別子を参照できる方法(f#4.1 spec 6.6 definition expression)
の2種類があります。
それぞれについて、関数の束縛と値の束縛のための構文が存在しますが、
それらの構文の中身はAB共通です。
このページではこのうち、値を束縛する際の構文について説明します。
Aの形式は後に説明するモジュールの構文の一部になっていて
そのモジュールのトップレベルに識別子が定義されます。
この形式で定義した値のことはnamed valueと言います(f#4.1 spec 10.2.1)
現時点では、1つしかファイルを使わない場合は
モジュールや名前空間のことは考えなくても問題ない(f#4.1 spec 12.1)と考えて良いです。
このあたりの事はモジュールの章で説明予定です。
letを使う構文を(説明する範囲に絞って)簡略化したものは次のようになります
(正確な構文を知りたい人はページ下部へ)
- letで値を束縛するための構文
- let pat return-typeopt = expr --Aの構文
let pat return-typeopt in expr --Bの構文
pat:パターンのこと。今は識別子のことだと思っていてください。後に色々出てきます
return-typeopt:返り値の型、省略可能。let a : int=1といった具合に(: 型名)として指定
expr:式。F#での様々な計算を表します。単なる値(数値の1とか)も式になります。
patのうち、識別子(いわゆる変数名)に使える文字は、(他の構文とかぶらなければ)
先頭文字:UnicodeのLu,Ll,Lt,Lm,Lo,Nlに相当するクラスの文字(英数字ほか)と_(アンダースコア)
先頭以外の文字:先頭文字に加えて、数字、UnicodeのPc,Mn,Mc,Cfに相当するクラスの文字
が使えます(f#4.1 spec 3.4)
Unicodeの文字クラスについては
MSDN:文字クラス参照
最初の例をBの構文で書くと次のようになります。
let binding expression
> let b = 1 in b;;
val it : int = 1
> let c = 1 in c+10;;
val it : int = 11
> b;;
b;;
^
stdin(4,1): error FS0039: The value or constructor 'b' is not defined
この方式では、inから、文の終わり(;;)までの間で、一時的に識別子が使えますが
識別子はモジュールには定義されないため
上のようにinの有効範囲を抜けた後でアクセスしようとしてもエラーになります。
こうした、識別子を参照出来る範囲のことを
スコープ(scope)と言います。
letによる定義が作るスコープはレキシカルスコープです(f#4.1 spec 6.6)
(レキシカルスコープの意味やスコープについては別途説明予定です)
ある識別子が利用可能なスコープの中で
同名の識別子をletで定義した場合、
以前の識別子は隠れて、新しい識別子だけが参照出来るようになります。
同名の識別子とスコープ
> let d = 10;; //トップレベルのd
val d : int = 10
> let d = 20 in d;; //このinの中では、新しいdが有効
val it : int = 20
> d;; //トップレベルのdが有効
val it : int = 10
最後に、letの正確な構文は次のようになります(f#4.1 spec 6[構文B],10[構文A])
- letの構文
- attributesopt let recopt function-or-value-defns --Aの構文
function-or-value-defns := function-or-value-defn and ... and function-or-value-defn
function-or-value-defn :=
function-defn
value-defn
function-defn :=
inlineopt accessopt ident-or-op typar-defnsopt argument-pats return-typeopt = expr
value-defn :=
mutableopt accessopt pat typar-defnsopt return-typeopt = expr
let function-defn in expr –- Bの構文
let value-defn in expr –- Bの構文
let rec function-or-value-defns in expr -- Bの構文