Если вы хотите, чтобы ваша процедура могла дублировать любой объект, то этот объект может быть любым из базовых типов Схемы. В силу того, что является различными типами, они имеют разные«Природы», или структура, или что у вас есть, и поэтому создание копии объекта одного типа обязательно будет включать разные стратегии, чем создание копии другого объекта другого типа.
Так какВы подходите к этому, чтобы исследовать каждый из типов Схемы (или, вернее, подмножество типов Схемы, с которыми вам нужно работать) и выяснить, что означает дублирование объекта этого типа.Если вы делаете это очевидным образом, вы должны получить набор специализированных процедур, таких как COPY-NUMBER, COPY-SYMBOL и т. Д. (Спойлер: многие из этих процедур не будут очень интересными.)
Объединение этих специализированных процедур в одну процедуру, которая может дублировать любой объект, который вы даете, сводится к определению реального типа объекта и вызову процедуры COPY-FOO для выполнения работы (вы также можете расширить процедурув соответствии).Вы можете действительно легко организовать это с помощью COND и предикатов определения типа:
(define (copy-object obj)
(cond ((number? obj) (copy-number obj))
((boolean? obj) (copy-boolean obj))
...
))
Это общий шаблон проектирования для выполнения операции с датумом независимо от его типа, называемого «диспетчеризация по типу».На самом деле это довольно плохой способ сделать общее программирование, не то, чтобы это имело слишком большое значение в этой ситуации.
Последнее, что нужно добавить, это то, что вы возвращаете то, что вы можете оценить, чтобы получить копии.Могу также сказать вам, что это прямо: инкапсулировать вызов COPY-OBJECT внутри лямбда-выражения без аргументов:
(define (expr-returning obj)
(lambda () (copy-object obj)))
Тогда вы можете делать такие вещи, как
guile> (define x (list 1 2 3 4))
guile> (define y (expr-returning x))
guile> (define cx (y))
guile> x
(1 2 3 4)
guile> cx
(1 2 3 4)
guile> (set-cdr! x 'foo)
guile> x
(1 . foo)
guile> z
(1 2 3 4)
<i>etc.</i>