(defun cdddar (x) (cdr (cddar x)))
(defun cddddr (x) (cdr (cdddr x)))
+(defun sublis (alist tree &key key (test #'eql testp) (test-not #'eql test-not-p))
+ (labels ((s (tree)
+ (when (and testp test-not-p)
+ (error "Both test and test-not are set"))
+ (let* ((key-val (if key (funcall key tree) tree))
+ (replace (if test-not-p
+ (assoc key-val alist :test-not test-not)
+ (assoc key-val alist :test test)))
+ (x (if replace (cdr replace) tree)))
+ (if (atom x)
+ x
+ (cons (s (car x)) (s (cdr x)))))))
+ (s tree)))
(defun copy-list (x)
(mapcar #'identity x))
prog2 progn psetq push quote rassoc read-from-string remove remove-if
remove-if-not return return-from revappend reverse rplaca rplacd
second set setf setq seventh sixth some string string-upcase string=
- stringp subseq subst symbol-function symbol-name symbol-package
+ stringp sublis subseq subst symbol-function symbol-name symbol-package
symbol-plist symbol-value symbolp t tagbody tailp tenth third throw
tree-equal truncate unless unwind-protect values values-list variable
vector-push-extend warn when write-line write-string zerop))
(test (equal (cdddar '((1 2 3 4))) '(4)))
(test (equal (cddddr '(1 2 3 4 5)) '(5)))
+;; SUBLIS
+(test (equal (sublis '((x . 100) (z . zprime))
+ '(plus x (minus g z x p) 4 . x))
+ '(PLUS 100 (MINUS G ZPRIME 100 P) 4 . 100)))
+(test (equal (sublis '(((+ x y) . (- x y)) ((- x y) . (+ x y)))
+ '(* (/ (+ x y) (+ x p)) (- x y))
+ :test #'equal)
+ '(* (/ (- X Y) (+ X P)) (+ X Y))))
+(let ((tree1 '(1 (1 2) ((1 2 3)) (((1 2 3 4))))))
+ (test (equal (sublis '((3 . "three")) tree1)
+ '(1 (1 2) ((1 2 "three")) (((1 2 "three" 4))))))
+ (test (equal (sublis '((t . "string"))
+ (sublis '((1 . "") (4 . 44)) tree1)
+ :key #'stringp)
+ '("string" ("string" 2) (("string" 2 3)) ((("string" 2 3 44))))))
+ (test (equal tree1 '(1 (1 2) ((1 2 3)) (((1 2 3 4)))))))
+(let ((tree2 '("one" ("one" "two") (("one" "Two" "three")))))
+ (test (equal (sublis '(("two" . 2)) tree2)
+ '("one" ("one" "two") (("one" "Two" "three")))))
+ (test (equal tree2 '("one" ("one" "two") (("one" "Two" "three")))))
+ (test (equal (sublis '(("two" . 2)) tree2 :test 'equal)
+ '("one" ("one" 2) (("one" "Two" "three"))))))
+
; COPY-TREE
(test (let* ((foo (list '(1 2) '(3 4)))
(bar (copy-tree foo)))