F#の値
F#の値は、特定の "型" をもっています。値は必ず、以下のいずれかの型となります。
整数 |
浮動小数点数 |
文字 |
文字列 |
リスト |
シーケンス |
配列 |
タプル |
判別共用体 |
レコード |
クラス型 |
関数値 |
型の詳細は "F#の型" の章で紹介します。
値の束縛
束縛, またはバインドとは、"名前" と "定義" を関連付けること(= バインディング)を指します。letキーワードは次のように値のバインディングを行います。
let x = 1 // int型
let y = 100u // unsigned int型
let s = "test" // string型
// 関数値のバインディング
let f x = x**2 // xを2乗する関数
例のように "let" を利用して "名前" と "定義" をバインディングすることを "let束縛" または "letバインディング" といいます。 また、値の "型" は、定義(= 右辺)から自動的に推論されます。整数や浮動小数点数型などのF#組み込み型については "型リテラル" の型から判断されます。 型リテラルは、 "F#の型" の各型の項目で紹介します。
letバインディングされた値は、基本的に不変な値(= 変更不可能な値)となっています(= immutable)。
immutableな値は、プログラムの実行過程全体を通じて変更ができません。C#やVB.NETなどの関数型言語以外の言語に慣れ親しんでいる場合、変更可能な値(= 変数)ではなく 変更不可能な値が使用されることに違和感を覚えるかもしれません。しかし、この "値は基本的に変更されない" という大前提が関数型プログラミングでは非常に重要な要素と なります。
マルチスレッド環境では、多数の異なるスレッドから変更される共有変数を管理することは非常に難しいです。また、変数が別の関数に渡されたときに変更される可能性があるか どうかを見分けることが難しい場合があります。こういった問題に対して "immutableな値" が既定であることが優位に働きます(詳細は別章)。
特に純粋な関数型言語では、変数は存在せず、関数は数学関数として厳密に機能します。手続き型言語のコードでは代入などの変数割り当てを使用して値を変更しますが、関数型 言語の場合には、(1)immutableな入力値, (2)immutableな関数, (3)immutableな出力値 であらわされます。この数学的な厳密性によって、強力な型推論が実現可能となっています。 この強力な型推論により、コンパイラでコードをより厳密にチェックし、より効率的な最適化が行われ、開発者が正しいコードを容易に理解・記述できるようになります。
このような仕組みのおかげで、関数型言語でのプログラミングにおいては、通常の手続き型プログラミングよりもデバッグが容易になることが普通です。
F#は、純粋な関数型言語ではないですが、関数型プログラミングを完全にサポートしています。 immutableな値を使用することは、コーディングにおいて関数型プログラミングの重要な特長を利用するための優れた方法です。
変更可能な値
F#は純粋な関数型言語ではないため、変更可能な値(= mutableな値)を利用することも可能です。 その場合、let束縛に mutableキーワードを使用します。
F#でのmutableな値の使える範囲は、通常、型のフィールド、または、ローカル値のみに限定されています。mutableな値を利用できる範囲を限定することによって、 制御を容易にして、誤った方法で値が変更される可能性を低くくしています。
新しい値を割り当てる場合、<-演算子 を使用して再割り当てを行います。以下が mutableな値 の簡単な例になります。
let mutable x = 1
x <- x + 1