datatype 'a tree =
LEAF of 'a
| NODE of ('a tree * 'a tree)
と書くことで, 型パラメータを'aをとる型treeを定義したことにな
り, プログラムで以降, int tree, real treeなどの型が使え
るようになる. また, それら全てのtree型に有効な関数を書くことができる.
例えば,
fun is_leaf (LEAF x) = true | is_leaf (NODE (left, right)) = falseは, 全ての
'a tree型に対して有効である.
同様の機構は, Eiffelなどの多くのオブジェクト指向言語でもサポートされて いる.
ABCL/fの構文ではdeftypeおよびdefclassにおいて型パ
ラメータを指定する場所が用意されている. 例えば本来は上述のtree
は,
(deftype tree (a) (leaf a) (node (tree a) (tree a)))と書けるはずである. 同様に,
defclassにおいても,
(defclass tree (a) ...)のように書けるはずである. しかし現在の処理系ではこれらはサポートされて いない. いいかえれば,
deftypeおよびdefclassの型パラメー
タ部分は常に空(つまり())でなくてはならない. これに違反したプロ
グラムに対して, コンパイラは以下のようにエラーメッセージを出す.
Expand Error: deftype type parameters ignored (deftype tree (a) (leaf a) (node (tree a) (tree a)))
defvar, defconstantの不完全な実装
(defvar *x* (+ 3 4))などは許されるが,
(defvar *x* (foo 3))などは許されない. 現在, これに違反したプログラムも, warningを出すのみで, ABCL/fからC++への変換は成功してしまう. し かし生成されたC++プログラムをオブジェクトファイルにする際にC++コンパイ ラによって, エラーとなる. たとえば,
(defun foo (x) (declare (fixnum x) (reply-type fixnum)) x) (defvar *x* (foo 3))というファイルをコンパイルすると, ABCL/fからC++への変換時には,
lute:1010% make x.o abclfc -f sun -debugger :off x.ff x.cc ABCLF_ROOT = /home/users/tau/proj/abclf ; Loading #p"/tmp_mnt/home/camille2/tau/proj/abclf/lib/init.abclfc". Converting defun foo Converting defvar *x* Warning: Initializing defvar/defconstant by compound expression is not fully implemented. You may get C++ compiler error. ...のようなwarningが出るのみで, のちにC++コンパイラによって,
x.cc:1035: braced-group within expression allowed only inside a functionというエラーメッセージが出される.
Becomeは, defmethod!の中で正確に一度だけ実行されなくては
ならない. 例えば以下のようなプログラムは不正なプログラムである.
(defmethod! counter add2 (x) (declare (fixnum x) (reply-type fixnum)) (become val :val (+ val x)) (become val :val (+ val x)))しかし現在のコンパイラはこのことを検出しない. また, よりおきがちな誤り として, 以下のようなものもあり得る.
(defmethod! counter add-if-large (x)
(declare (fixnum x) (reply-type fixnum))
(if (> x 10)
(become val :val (+ val x))
val))
これは, xが10より大きい場合にのみcounterの値を更新することを意
図したものだが, そうでない場合にbecomeが一度も実行されないので
誤りである. 上のプログラムは,
(defmethod! counter add-if-large (x)
(declare (fixnum x) (reply-type fixnum))
(if (> x 10)
(become val :val (+ val x))
(become val)))
と書かなくてはならない.
上のような意味で誤った実行をしてしまった場合, 現処理系は実行時エラーを 生成する. エラーはbecomeを一度も実行せずにmethodを終了した時点, ある いは, 2度目のbecomeを実行しようとした時点で生成される.