(<- (member ?item (?item . ?))) (<- (member ?item (? . ?rest)) (member ?item ?rest))これを処理するには,節の中に?があれば それを同じ変数に置き換えるということを すればよいので以下のように
(defmacro <- (&rest clause) `(add-clause ',(replace-?-vars clause))) (defmacro ?- (&rest goals) `(top-level-prove ',(replace-?-vars goals))) (defun replace-?-vars (exp) (cond ((eq exp '?) (gensym "?")) ((atom exp) exp) (t (cons (replace-?-vars (car exp)) (replace-?-vars (cdr exp))))))これにより,
[4]> (?- (member ? (1 2 3))) ?325 = 1; ?325 = 2; ?325 = 3; No. [5]> (?- (member ?x (1 2 3))) ?X = 1; ?X = 2; ?X = 3; No.という形になる. ここで,?の変数が入っていない場合にも consによってメモリを消費するので, 入っていない場合にはconsしない という具合にすれば効率がよいので 次のようにする.
(defun replace-?-vars (exp) (cond ((eq exp '?) (gensym "?")) ((atom exp) exp) (t (reuse-cons (replace-?-vars (car exp)) (replace-?-vars (cdr exp)) exp)))) (defun reuse-cons (x y x-y) (if (and (eql x (car x-y)) (eql y (cdr x-y))) x-y (cons x y)) )(reuse-cons x y x-y)は x-yのcar が xで cdrがyと同じで あればconsせずにx-yをそのまま 使うというものである.