User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:functions:sublis [2019/09/14 05:00]
cl:functions:sublis [2019/09/20 08:00] (current)
Line 1: Line 1:
 +====== Function SUBLIS, NSUBLIS ======
  
 +====Syntax====
 +**sublis ** //alist tree ''&​key''​ key test test-not// → //​new-tree//​
 +**nsublis** //alist tree ''&​key''​ key test test-not// → //​new-tree//​
 +
 +====Arguments and Values====
 +  * //alist// - an //​[[CL:​Glossary:​association list]]//.
 +  * //tree// - a //​[[CL:​Glossary:​tree]]//​.
 +  * //test// - a //​[[CL:​Glossary:​designator]]//​ for a //​[[CL:​Glossary:​function]]//​ of two //​[[CL:​Glossary:​argument|arguments]]//​ that returns a //​[[CL:​Glossary:​generalized boolean]]//​.
 +  * //​test-not//​ - a //​[[CL:​Glossary:​designator]]//​ for  a //​[[CL:​Glossary:​function]]//​ of two //​[[CL:​Glossary:​argument|arguments]]//​ that returns a //​[[CL:​Glossary:​generalized boolean]]//​.
 +  * //key// - a //​[[CL:​Glossary:​designator]]//​ for a //​[[CL:​Glossary:​function]]//​ of one [[CL:​Glossary:​argument]],​ or **[[CL:​Constant Variable:​nil]]**.
 +  * //​new-tree//​ - a //​[[CL:​Glossary:​tree]]//​.
 +
 +====Description====
 +**sublis** makes substitutions for //​[[CL:​Glossary:​object|objects]]//​ in //tree// (a structure of //​[[CL:​Glossary:​cons|conses]]//​).
 +
 +**nsublis** is like **sublis** ​ but destructively modifies the relevant parts of the //tree//.
 +
 +**sublis** looks at all subtrees and leaves of //tree//; if a subtree or leaf appears as a key in //alist// (that is, the key and the subtree or leaf //​[[CL:​Glossary:​satisfy the test]]//), it is replaced by the //​[[CL:​Glossary:​object]]//​ with which that key is associated. This operation is non-destructive. ​ In effect, **sublis** can perform several **[[CL:​Functions:​subst]]** operations simultaneously.
 +
 +If **sublis** succeeds, a new copy of //tree// is returned in which each occurrence of such a subtree or leaf is replaced by the //​[[CL:​Glossary:​object]]//​ with which it is associated. ​  If no changes are made, the original tree is returned. ​ The original //tree// is left unchanged, but the result tree may share cells with it.
 +
 +**nsublis** is permitted to modify //​tree// ​ but otherwise returns the same values as **sublis**.
 +
 +====Examples====
 +<​blockquote>​
 +;;; TODO fix indentation on this one
 +(sublis '((x . 100) (z . zprime)) '(plus x (minus g z x p) 4 . x))
 +<​r>​(PLUS 100 (MINUS G ZPRIME 100 P) 4 . 100)</​r>​
 +(sublis '(((+ x y) . (- x y)) ((- x y) . (+ x y))) '(* (/ (+ x y) (+ x p)) (- x y)) :test #'​[[CL:​Functions:​equal]]) ​
 +<r>(* (/ (- X Y) (+ X P)) (+ X Y))</​r>​
 +([[CL:​Macros:​defparameter]] //​*tree-1*//​ '(1 (1 2) ((1 2 3)) (((1 2 3 4))))) <​r>​*TREE-1*</​r>​
 +(sublis '((3 . "​three"​)) //​*tree-1*//​) <r>(1 (1 2) ((1 2 "​three"​)) (((1 2 "​three"​ 4))))</​r>​
 +(sublis '((t . "​string"​)) (sublis '((1 . ""​) (4 . 44)) //​*tree-1*//​) :key #'​[[CL:​Functions:​stringp]]) <​r>​("​string"​ ("​string"​ 2) (("​string"​ 2 3)) ((("​string"​ 2 3 44))))</​r>​
 +//​*tree-1*//​ <r>(1 (1 2) ((1 2 3)) (((1 2 3 4))))</​r>​
 +([[CL:​Macros:​defparameter]] //​*tree-2*//​ '​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​)))) <​r>​*TREE-2*</​r>​
 +(sublis '​(("​two"​ . 2)) //​*tree-2*//​) <​r>​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​))) </r>
 +//​*tree-2*//​ <​r>​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​))) </r>
 +(sublis '​(("​two"​ . 2)) //​*tree-2*//​ :test #'​[[CL:​Functions:​equal]]) <​r>​("​one"​ ("​one"​ 2) (("​one"​ "​Two"​ "​three"​))) </r>
 +
 +(nsublis '((t . '​temp)) //​*tree-1*//​ :key #'​([[CL:​Macros:​lambda]] (//x//) ([[CL:​Macros:​or]] ([[CL:​Functions:​atom]] //x//) ([[CL:​Functions:​less|<​]] ([[CL:​Functions:​list-length]] //x//) 3)))) <​r>​((QUOTE TEMP) (QUOTE TEMP) QUOTE TEMP) </r>
 +</​blockquote>​
 +
 +====Side Effects====
 +**nsublis** modifies //tree//.
 +
 +====Affected By====
 +None.
 +
 +====Exceptional Situations====
 +None.
 +
 +====See Also====
 +**[[CL:​Functions:​subst|Function SUBST]]**, {\secref\ConstantModification},​ {\secref\TraversalRules}
 +
 +====Example Implementation====
 +To be done.
 +
 +====Notes====
 +The **'':​test-not''​** parameter is deprecated.
 +
 +Because the side-effecting variants (//e.g.// **nsublis**) potentially change the path that is being traversed, their effects in the presence of shared or circular structure structure may vary in surprising ways when compared to their non-side-effecting alternatives. ​ To see this, consider the following side-effect behavior, which might be exhibited by some implementations:​
 +
 +<​blockquote>​
 +([[CL:​Macros:​defun]] test-it (//f//n)
 +  ([[CL:​Special Operators:​let-star|let*]] ((//​shared-piece//​ ([[CL:​Functions:​list]] 'a 'b))
 +         ​(//​data//​ ([[CL:​Functions:​list]] //​shared-piece//​ //​shared-piece//​)))
 +    ([[CL:​Functions:​funcall]] //fn// '((a . b) (b . a)) data)))
 +<​r>​TEST-IT</​r>​
 +(test-it #'​sublis) <​r>​((B A) (B A))</​r>​
 +(test-it #'​nsublis) <​r>​((A B) (A B))</​r>​
 +</​blockquote>​
 +
 +\issue{DOTTED-LIST-ARGUMENTS:​CLARIFY}
 +\issue{TEST-NOT-IF-NOT:​FLUSH-ALL}
 +\issue{CONSTANT-MODIFICATION:​DISALLOW}
 +\issue{MAPPING-DESTRUCTIVE-INTERACTION:​EXPLICITLY-VAGUE}