% Function SUBLIS, NSUBLIS
Function SUBLIS
, NSUBLIS
sublis
alist tree &key key test test-not => new-tree
nsublis
alist tree &key key test test-not => new-tree
alist - 連想リスト
tree - ツリー
test - 2つの引数を取りgeneralized-booleanを返却する関数の指定子
test-not - 2つの引数を取りgeneralized-booleanを返却する関数の指定子
key - 1つの引数を取りgeneralized-booleanを返却する関数の指定子、
またはnil
new-tree - ツリー
sublis
は、tree(コンスの構造)をオブジェクトに置換します。
nsublis
はsublis
と似ていますが、
treeの関連する部分を破壊的に修正します。
sublis
は、treeの部分ツリーと葉を全て見ます。
もし部分ツリーか葉がalistのキーとして現れたとき
(つまりキーと、部分ツリーか葉がtestを満たすとき)、
それはキーに連想されているオブジェクトに置き換えられます。
この操作は非破壊的です。
実際には、sublis
は複数のsubst
の操作を同時に
行うようなものです。
sublis
が成功すると、
指定された部分ツリーと葉が出現された各部分が、
関連付けらているオブジェクトで置き換わった
新しいツリーが返却されます。
もし変更が生じなかったときは、もとのtreeが返却されます。
元のtreeに変更は生じないとしても、返却値のツリーは
元のツリーとセルを共有しているかもしれません。
nsublis
はtreeの変更を許可されていますが、
それ以外はsublis
と同じ値を返却します。
(sublis '((x . 100) (z . zprime))
'(plus x (minus g z x p) 4 . x))
=> (PLUS 100 (MINUS G ZPRIME 100 P) 4 . 100)
(sublis '(((+ x y) . (- x y)) ((- x y) . (+ x y)))
'(* (/ (+ x y) (+ x p)) (- x y))
:test #'equal)
=> (* (/ (- X Y) (+ X P)) (+ X Y))
(setq tree1 '(1 (1 2) ((1 2 3)) (((1 2 3 4)))))
=> (1 (1 2) ((1 2 3)) (((1 2 3 4))))
(sublis '((3 . "three")) tree1)
=> (1 (1 2) ((1 2 "three")) (((1 2 "three" 4))))
(sublis '((t . "string"))
(sublis '((1 . "") (4 . 44)) tree1)
:key #'stringp)
=> ("string" ("string" 2) (("string" 2 3)) ((("string" 2 3 44))))
tree1 => (1 (1 2) ((1 2 3)) (((1 2 3 4))))
(setq tree2 '("one" ("one" "two") (("one" "Two" "three"))))
=> ("one" ("one" "two") (("one" "Two" "three")))
(sublis '(("two" . 2)) tree2)
=> ("one" ("one" "two") (("one" "Two" "three")))
tree2 => ("one" ("one" "two") (("one" "Two" "three")))
(sublis '(("two" . 2)) tree2 :test 'equal)
=> ("one" ("one" 2) (("one" "Two" "three")))
(nsublis '((t . 'temp))
tree1
:key #'(lambda (x) (or (atom x) (< (list-length x) 3))))
=> ((QUOTE TEMP) (QUOTE TEMP) QUOTE TEMP)
nsublis
はtreeを修正します。
なし。
なし。
subst
,
3.2.1. コンパイラーの用語,
3.6. 横断の規則と副作用
:test-not
パラメーターは非推奨です。
副作用による変形(nsublis
など)は、
通過するパスを変更する可能性があるので、
共有構造や循環構造が現れるものでは、
副作用による修正がないものと比べると、
驚くべき方法で変化する可能性があります。
このような挙動を見るために、
いくつかの実装では見られるかもしれない、
次のような副作用の動作を考えてみましょう。
(defun test-it (fn)
(let* ((shared-piece (list 'a 'b))
(data (list shared-piece shared-piece)))
(funcall fn '((a . b) (b . a)) data)))
(test-it #'sublis) => ((B A) (B A))
(test-it #'nsublis) => ((A B) (A B))