% 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))