左辺値と参照渡し

もっとも単純な形として、左辺値はポインタの指す位置に保存された (なんらかの型の) 値を証言している線形の証明とペアになった単なるポインタです。 左辺値 (left-value) という名前は、(C言語のように) 割り当てられた文の左側に置かれることが許された値に由来します。 しばしば直感的に、左辺値はアドレスが付属した値として説明されます。 左辺値として選ばれたどのような表現も、 ポインタと左辺値に関連する (なんらかの駐観の) 線形の証明の両方ともを識別できなければならないことに注意してください。

ATS では、もっとも単純な左辺値を表わす式は !p です。 このとき ! は特殊記号で、p はどこかのアドレス L について型 ptr(L) の値です。 この式が型検査される時、 なんらかの型 T について T@L の証明が現状有効な証明群の中に見つかることを要求します。 徐々にさらなる左辺値の形について紹介します。

ATS における関数へ引数を渡す既定の戦略は値渡し (call-by-value) です。 けれども、特定の関数に渡す引数に参照渡し (call-by-reference) を選択するように指示することも ATS では可能です。 参照渡しの場合、渡される引数は左辺値でなければなりません。 そして実際には (アドレスに格納された値の代わりに) 左辺値のアドレスが渡されることになります。 例えば、次に定義した関数 swap2 は参照渡しを使っています:

fn{ a:t@ype } swap2 ( x1: &a, x2: &a ) : void = let val tmp = x1 in x1 := x2; x2 := tmp end // end of [swap2]

関数の引数の型の直前にある特殊記号 & は、その引数が参照渡し戦略に従って渡される必要があることを示すことに注意してください。 次のコードは swap2 を元にして swap1 を実装しています:

fn{ a:t@ype } swap1{l1,l2:addr} ( pf1: !a @ l1, pf2: !a @ l2 | p1: ptr l1, p2: ptr l2 ) : void = swap2 (!p1, !p2)

呼び出し swap2(!p1, !p2) が実行時に評価された時、(この2つのポインタは指す位置に保管されている値ではなく) 2つのポインタ p1p2 が実際にはパラメータとして渡されます。

型 T と整数 N が与えられた時、構文 @[T][N] は 型 T の要素数 N から成るフラットな配列を表わしています。 型 @[T][N] の値のサイズは N*sizeof(T) であることに注意してください。 もし関数が配列を表わすパラメータを持つなら、このパラメータは参照渡しの方が好ましいでしょう。 例えば、次のコードは double の2つの配列を取り、ドット積 (またはスカラー積) を計算する関数を実装しています:

fun dotprod ( A: &(@[double][3]) , B: &(@[double][3]) ) : double = ( A[0] * B[0] + A[1] * B[1] + A[2] * B[2] )

dotprod の配列引数は両方とも参照渡しであることに注意してください。