В Лиспе все аргументы всегда передаются по значению.Если вы хотите изменить содержимое структуры, которую вы передаете, вы можете сделать это, указав, что вы хотите изменить:
(defstruct node farmer fox goose straw)
(defparameter *node* (make-node :fox 3))
(defun change-slot (object slot-name new-value)
(setf (slot-value object slot-name) new-value))
(change-slot *node* 'fox 7)
(change-slot *node* 'goose 23)
*node*
==> #S(NODE :FARMER NIL :FOX 3 :GOOSE 23 :STRAW NIL)
Обратите внимание, что, хотя стандарт не требует slot-value
для работы на structure-object
, приведенный выше код работает на всех реализациях CL.
Если вы хотите, чтобы ваш код соответствовал ,Вы должны передать setter :
(defun change-slot (object setter new-value)
(funcall setter new-value object))
(change-slot *node* #'(setf node-farmer) 6)
*node*
==> #S(NODE :FARMER 6 :FOX 3 :GOOSE 23 :STRAW NIL)
Это, увы, не гарантированно сработает либо , потому что :
этозависит от реализации, реализована ли возможность записи слота функцией setf или расширителем setf.
Таким образом, вам нужно создать свой собственный установщик:
(change-slot *node* (lambda (straw node) (setf (node-straw node) straw)) 11)
*node*
==> #S(NODE :FARMER 6 :FOX 3 :GOOSE 23 :STRAW 11)