# Differences

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

 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)​ + (sublis '(((+ x y) . (- x y)) ((- x y) . (+ x y))) '(* (/ (+ x y) (+ x p)) (- x y)) :test #'​[[CL:​Functions:​equal]]) ​ + (* (/ (- X Y) (+ X P)) (+ X Y))​ + ([[CL:​Macros:​defparameter]] //​*tree-1*//​ '(1 (1 2) ((1 2 3)) (((1 2 3 4))))) <​r>​*TREE-1*​ + (sublis '((3 . "​three"​)) //​*tree-1*//​) (1 (1 2) ((1 2 "​three"​)) (((1 2 "​three"​ 4))))​ + (sublis '((t . "​string"​)) (sublis '((1 . ""​) (4 . 44)) //​*tree-1*//​) :key #'​[[CL:​Functions:​stringp]]) <​r>​("​string"​ ("​string"​ 2) (("​string"​ 2 3)) ((("​string"​ 2 3 44))))​ + //​*tree-1*//​ (1 (1 2) ((1 2 3)) (((1 2 3 4))))​ + ([[CL:​Macros:​defparameter]] //​*tree-2*//​ '​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​)))) <​r>​*TREE-2*​ + (sublis '​(("​two"​ . 2)) //​*tree-2*//​) <​r>​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​))) + //​*tree-2*//​ <​r>​("​one"​ ("​one"​ "​two"​) (("​one"​ "​Two"​ "​three"​))) + (sublis '​(("​two"​ . 2)) //​*tree-2*//​ :test #'​[[CL:​Functions:​equal]]) <​r>​("​one"​ ("​one"​ 2) (("​one"​ "​Two"​ "​three"​))) + + (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) + ​ + + ====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​ + (test-it #'​sublis) <​r>​((B A) (B A))​ + (test-it #'​nsublis) <​r>​((A B) (A B))​ + ​ + + \issue{DOTTED-LIST-ARGUMENTS:​CLARIFY} + \issue{TEST-NOT-IF-NOT:​FLUSH-ALL} + \issue{CONSTANT-MODIFICATION:​DISALLOW} + \issue{MAPPING-DESTRUCTIVE-INTERACTION:​EXPLICITLY-VAGUE}

### Page Tools 