Return a new structure with changed fields

I am looking for an easy way to return a new structure that is a copy of the existing one with some changed fields, without changing the original.

I get that you can use setfto modify data in one of the fields, for example:

[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

But, as I said, this significantly destroys the source data, and this is not what I'm going to do.

I could, of course, do something like this:

(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

But it seems more like work than anything.

In Erlang, you can do something like this:

-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

No data changed.

PS Yes, I know that Common Lisp is not Erlang; but Erlang has simplified the work with records / structures invariably, and since the functional style is promoted in Common Lisp, it would be nice if there was a similar opportunity.

+4
1

Erlang records Prolog. , , update_struct/4, : . Erlang, . Common Lisp , update-struct:

(defun update-struct (struct &rest bindings)
  (loop
    with copy = (copy-structure struct)
    for (slot value) on bindings by #'cddr
    do (setf (slot-value copy slot) value)
    finally (return copy)))

CL-USER> (defstruct foo bar baz)
FOO
CL-USER> (defparameter *first* (make-foo :bar 3))
*FIRST*
CL-USER> (defparameter *second* (update-struct *first* 'baz 2))
*SECOND*
CL-USER> (values *first* *second*)
#S(FOO :BAR 3 :BAZ NIL)
#S(FOO :BAR 3 :BAZ 2)

, :

undefined: SLOT-VALUE undefined. , . , , , , - GCL.

, HyperSpec SLOT-VALUE:

, , .

-, (. :TYPE). , , . lisp: - .

, .

, x:

(:a 10 :b 30)

(list* :b 0 x) - :

(:b 0 :a 10 :b 30) 

... , :b, , (. GETF).

bindings - (, ). LOOP , ON, , . , (loop for x on '(a b c d)) x (a b c d), (b c d), (c d) , , (c).

, BY, CDDR CDR ( ). / slot value .

+4

Source: https://habr.com/ru/post/1648146/


All Articles