おそらく、ATS はコードを書き下すことが簡単なプログラミング言語ではないでしょう。 ATS は安全な低レイヤープログラミングをサポートするために多くの機能を提供しています。 プログラマがそれらの機能を学習して使いこなせるようになるまでに、 長い時間とある程度の努力を費やす必要があるかもしれません。 この章では、C言語スタイルで書かれた ATS コードをいくつか紹介します。 これは、ATS プログラミングにおける安全ではない機能の典型的な使い方で、 C言語コードを書き慣れたプログラマにとってなじみ深いプログラミングスタイルです。
安全でないC言語スタイルプログラミングが懸命である場合があります。 ときには単に実行できる実装を手に入れて、バグを見つけて修正するためにテストを信頼しようとするかもしれません。 ときには安全に関数を実装する ATS プログラミングの作法を、熟知していない場合もあるでしょう。 またそれは単に個人の要望であるかもしれません。 私自身しばしば安全ではないC言語スタイルの ATS プログラミングをすることがありますし、 ただ ATS でコードを書きたいのではなく高い生産性が欲しい人にとって、それが必要なスキルであることも理解できます。 安全ではないC言語スタイルの ATS プログラミングの具体例を見てみましょう。
2つの文字列を標準辞書式順序によって比較する関数を実装したくなったとします。 その関数に strcmp という名前を付けて、次のようなインターフェイスを与えましょう:
2つの文字列 str1 と str2 が与えられると、 strcmp(str1, str2) は 1, -1, 0 のいずれかを返します。 それぞれ str1 が str2 と比較して、 より大きいか、より小さいか、等しいことを表わしています。 strcmp の実装は次のようになるでしょう:staload UN = "prelude/SATS/unsafe.sats" (* ****** ****** *) implement strcmp (str1, str2) = let // fun loop (p1: ptr, p2: ptr): int = let // val c1 = $UN.ptr0_get<uchar> (p1) val c2 = $UN.ptr0_get<uchar> (p2) // in case+ 0 of | _ when c1 > c2 => 1 | _ when c1 < c2 => ~1 | _ (* c1 = c2 *) => ( if $UN.cast{int}(c1) = 0 then 0 else loop (ptr0_succ<uchar> (p1), ptr0_succ<uchar> (p2)) // end of [if] ) end (* end of [loop] *) // in loop (string2ptr(str1), string2ptr(str2)) end (* end of [strcmp] *)
この例の完全なコードは オンライン にあります。
strcmp のような関数を、 人によってはC言語で直接実装するかもしれません。 例えば、上記のATSによる strcmp 実装を翻訳すると、 strcmp のC言語による実装は次のようになるでしょう:
int strcmp (char *p1, char *p2) { int res ; unsigned char c1, c2; while (1) { c1 = *p1; c2 = *p2; if (c1 > c2) { res = 1; break; } ; if (c1 < c2) { res = -1; break; } ; if ((int)c1==0) { res = 0 ; break ; } else { p1++; p2++; } ; } return res ; }
リストに保存されている要素群を与えられた配列の中にコピーするような関数を作りたいとしましょう。 その関数に array_copy_from_list という名前を付けて、 次のようなインターフェイスを与えます:
型 T が与えられた時、array0(T) はポインタ p とサイズ n を内包する array0 の値を作り、 その p は型 T の要素を n 個保持するC言語スタイルの配列を指し示します。差し当り、array_copy_from_list(A, xs) が呼び出されたら、リスト xs の長さに等しい配列Aのサイズを要求しましょう。 ATS における array_copy_from_list の実装を次に示します。 この関数は、unsafe.sats で宣言されている安全でない関数 ptr0_set を使っています:
staload UN = "prelude/SATS/unsafe.sats" (* ****** ****** *) implement {a}(*tmp*) array_copy_from_list (A, xs) = let // fun loop ( p: ptr, xs: list0 (a) ) : void = ( case+ xs of | list0_nil () => () | list0_cons (x, xs) => let val () = $UN.ptr0_set<a> (p, x) in loop (ptr0_succ<a> (p), xs) end // end of [list0_cons] ) (* end of [loop] *) // in loop (array0_get_ref(A), xs) end // end of [array_copy_from_list]
この例の完全なコードは オンライン にあります。