Я ищу простой способ вернуть новую структуру, которая является копией существующей с некоторыми измененными полями, без изменения оригинала.
Я понимаю, что вы можете использовать setf
для изменения данных в одном из полей, например:
[1]> (defstruct foo bar)
FOO
[1]> (defvar quux (make-foo :bar 12))
QUUX
[1]> (foo-bar quux)
12
[1]> (setf (foo-bar quux) 15)
15
[1]> (foo-bar quux)
15
Но, как я уже сказал, это по существу уничтожает исходные данные, а это не то, к чему я стремлюсь.
Я мог бы, конечно, сделать что-то вроде этого:
(defstruct foo bar baz) ; define structure
(defvar quux (make-foo :bar 12 :baz 200)) ; make new instance
(defvar ping (copy-foo quux)) ; copy instance
(setf (foo-bar ping) 15) ; change the bar field in ping
Но это больше похоже на обходной путь, чем на что-либо еще.
В Erlang вы можете сделать что-то вроде этого:
-record(foo, {bar, baz}). % defines the record
example() ->
Quux = #foo{bar = 12, baz = 200}, % creates an instance of the record
Ping = Quux#foo{bar = 15}. % creates a copy with only bar changed
Данные не изменены.
PS Да, я знаю, что Common Lisp — это не Erlang; но Erlang сделал удобной неизменяемую работу с записями/структурами, и, поскольку в Common Lisp поощряется функциональный стиль, было бы неплохо, если бы была доступна аналогичная опция.