15.4 Замещение выражений

Для выполнения операции замещения в древовидной структуре cons-ячеек предоставлен ряд функций. Все эти функции принимают дерево и описание того, что на что необходимо заменить. Функции имеют копирующие и деструктивные версии, а также версии в которых замещение описывается либо двумя аргументами, либо ассоциативным списком.

Правила именования для этих функций и для их именованных параметров совпадают с правилами функций для последовательностей. Смотрите раздел 14.

[Функция] subst new old tree &key :test :test-not :key
[Функция] subst-if new test tree &key :key
[Функция] subst-if-not new test tree &key :key

(subst new old tree) создаёт копию дерева tree, замещая элемент old элементом new. Замещение происходит в любом месте дерева. Функция возвращает модифицированную копию дерева tree. Исходный объект tree не изменяется, но итоговое дерево может иметь общие с исходным части.

Например:

(subst ’tempest ’hurricane
       ’(shakespeare wrote (the hurricane)))
    (shakespeare wrote (the tempest))

(subst ’foo ’nil ’(shakespeare wrote (twelfth night)))
    (shakespeare wrote (twelfth night . foo) . foo)

(subst ’(a . cons) ’(old . pair)
       ’((old . spice) ((old . shoes) old . pair) (old . pair))
       :test #’equal)
    ((old . spice) ((old . shoes) a . cons) (a . cons))

Эта функция не является деструктивной. Она не изменяет car и cdr элементы уже существующего дерева. Можно определить subst так:

(defun subst (old new tree &rest x &key test test-not key)
  (cond ((satisfies-the-test old tree :test test
                             :test-not test-not :key key)
         new)
        ((atom tree) tree)
        (t (let ((a (apply #’subst old new (car tree) x))
                 (d (apply #’subst old new (cdr tree) x)))
             (if (and (eql a (car tree))
                      (eql d (cdr tree)))
                 tree
                 (cons a d))))))

Смотрите также substitute, которая проводит замещение только для верхнего уровня списка.


[Функция] nsubst new old tree &key :test :test-not :key
[Функция] nsubst-if new test tree &key :key
[Функция] nsubst-if-not new test tree &key :key

nsubst является деструктивным аналогом subst. В дереве tree любой элемент old заменяется на new.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9


[Функция] sublis alist tree &key :test :test-not :key

sublis выполняет замещение объектов в дереве (древовидной структуре из cons-ячеек). Первый аргумент sublis является ассоциативным списком. Второй аргумент — дерево, в котором выполняется замещение. sublis проходит по всему дереву включая листья, и если элемент встречается в качестве ключа в ассоциативном списке, то данный элемент заменяет на значение ключа. Данная операция не разрушает дерево. sublis может выполнять несколько subst операций за один раз. Например:

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

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9


[Функция] nsublis alist tree &key :test :test-not :key

nsublis похожа на sublis но деструктивно модифицирует необходимые элементы дерева tree.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9