(in-package "USER") (defun substitute! (new old list &key (test #'eql)) ;; ;; substitute .new. for all (potentially embedded) occurences of .old. in ;; .list.; substitutions are carried out non-destructively (.list. is _not_ ;; altered; e.g. ;; ;; ? (substitute! 42 3 '(1 2 (3 (4) 5 ((3 3))))) ;; --> (1 2 (42 (4) 5 ((42 42)))) ;; (cond ((null list) nil) ((atom list) (if (funcall test old list) new list)) (t (cons (substitute! new old (first list)) (substitute! new old (rest list)))))) (defun nsubstitute! (new old list &key (test #'eql)) ;; ;; change items just like substitute!() but alter .list. destructively; e.g. ;; ;; ? (defparameter *foo* '(1 2 (3 (4) 5 ((3 3))))) ;; --> *foo* ;; ? (nsubstitute! 42 3 '(1 2 (3 (4) 5 ((3 3))))) ;; --> (1 2 (42 (4) 5 ((42 42)))) ;; ? *foo* ;; --> (1 2 (42 (4) 5 ((42 42)))) ;; (unless (atom list) (loop for list on list ;; ignores the case (atom (cdr list)) when (consp (first list)) do (nsubstitute! new old (first list) :test test) when (funcall test (first list) old) do (setf (first list) new) when (and (atom (rest list)) ;; takes care of the case (atom (cdr list)) (funcall test (rest list) old)) do (setf (rest list) new))) list) (defun add! (offset list) ;; ;; add. offset. to all (potentially embedded) elements of .list. that are ;; integerp(); e.g. ;; ;; ? (add! 42 '((FOO . ((BAR . 1))) (BAZ . 1))) ;; --> ((FOO (BAR . 43)) (BAZ . 43)) ;; (cond ((null list) nil) ((integerp list) (+ list offset)) ((atom list) list) (t (cons (add! offset (first list)) (add! offset (rest list))))))