参照セルの概要
参照セルは、ref 演算子を利用して作成された可変な値を保持するコンテナのようなものです。構文自体も非常に簡単で、以下のようなものとなっています。
// -------------------------------------
// [ 構文 ]
ref expression
値に対して ref 演算子を使用することで、その値をカプセル化する新しい "参照セル" を作成することができます。基となった値は変更可能(= mutable) となるので、変更することが可能です。
また、参照セルはアドレスだけではなく、実際の値を保持しています。そのため、ポインタセルではなく、参照セルなわけですね。ref演算子で参照セルを作成すると、基となる値のコピーが参照セルの可変値として作成されます。
参照セルはコンテナのようなもののため、そのままでは参照セルが保持している値を利用することはできません。
参照セルの保持している値を利用するには、! (bang) 演算子を利用して間接参照する必要があります。また、参照セルの保持している値に再代入したい場合は、:= (代入演算子) を利用します。
以下に簡単なサンプルを示します。
サンプルを見ていただくとわかる通り、19行目で再代入した値にrefValueが変わっていることが出力結果からわかります。
また、参照セルには、:=演算子以外で値を書き換える方法がまだあります。それは、通常のmutableな値に再代入する際に利用する <-演算子です。
ただ、何度も言いますが、参照セルはコンテナのようなもののため、直接再代入することはできません。そのため、<-演算子を利用して再代入をする場合は、contentsフィールドか、Valueプロパティを経由して再代入します。
let refValue = ref 0;
// contentsフィールドを利用する場合.
refValue.contents <- 30
printfn "refValue= %A" refValue
printfn "!refValue= %d" !refValue
// output:
// refValue= {contents = 30;}
// !refValue= 30
// Valueプロパティを利用する場合.
refValue.Value <- 40
printfn "refValue= %A" refValue
printfn "!refValue= %d" !refValue
// output:
// refValue= {contents = 40;}
// !refValue= 40
このcontentsフィールドはMLとの互換性のために用意されているもののため、コンパイル時に警告を発します。そのため、MLとの互換性が必要にならない場合には、Valueプロパティを利用する方が良いでしょう。もし、MLと互換性をもたせたい場合には、コンパイラオプションで --mlcompatibility を指定すると、警告を無効化することができますので、警告が出て煩わしい場合には指定すると良いでしょう。