(defun substitute-bindings (bindings pattern) (cond ((null pattern) nil) ((variable-p pattern) (let ((v (get-binding pattern bindings))) (if v (binding-val v) pattern))) ((atom pattern) pattern) (t (cons (substitute-bindings bindings (car pattern)) (substitute-bindings bindings (cdr pattern))))))この定義は,バインディング情報が連想リスト,あるいは,構造体のどちらで あっても大丈夫な定義になっています.それは,バインディング情報への アクセス関数を用いて定義してあるからです. このように,あるデータタイプを決めた場合に,そのデータへのアクセス 関数を定義し,その関数のみを用いて上位の関数を定義するということを 行なうことで,データの内部表現を変更した場合に上位の関数の定義を 変更する必要はなくなります.
<cl> (substitute-bindings (match '(?x ?y) '(a b)) '(x ?x y (?y (?x) ((?y))))) (X A Y (B (A) ((B)))) <cl> (substitute-bindings (match '(?x ?y) '(a b)) '(x ?x y (?y (?x) ((?y ?z))))) (X A Y (B (A) ((B ?Z))))ちなみに,バインディング情報が連想リストで表現している場合には,sublis という組み込み関数を利用できます.sublisは連想リストとパターンを与えた 場合に,パターン中に現れる連想リストのキーデータを値データに置き換える ということを行なうものです. ?で始まる変数でなくても連想リストのキーに なっているデータを置き換える一般的なものです.
<cl> (sublis '((a . 1) (b . 2)) '(b (a c) a b)) (2 (1 C) 1 2) <cl> (sublis '((?x . a) (?y . b)) '(x ?x y (?y (?x) ((?y ?z))))) (X A Y (B (A) ((B ?Z)))) <cl> (match '(?x ?y) '(a b)) ((?Y . B) (?X . A)) <cl> (sublis (match '(?x ?y) '(a b)) '(x ?x y (?y (?x) ((?y ?z))))) (X A Y (B (A) ((B ?Z)))) <cl> (sublis '((x . 100) (z . zprime)) '(plus x (minus g z x p) 4 . x)) (PLUS 100 (MINUS G ZPRIME 100 P) 4 . 100) <cl> (sublis '(((+ x y) . (- x y)) ((- x y) . (+ x y))) '(* (/ (+ x y) (+ x p)) (- x y)) :test #'equal) (* (/ (- X Y) (+ X P)) (+ X Y)) <cl> (setq tree1 '(1 (1 2) ((1 2 3)) (((1 2 3 4))))) (1 (1 2) ((1 2 3)) (((1 2 3 4)))) <cl> (sublis '((3 . "three")) tree1) (1 (1 2) ((1 2 "three")) (((1 2 "three" 4)))) <cl> tree1 (1 (1 2) ((1 2 3)) (((1 2 3 4))))