Макрос cl-defstruct
создает средства доступа к слотам в форме NAME-SLOT
, где NAME
- это имя типа структуры, а SLOT
- это имя слота. Используя ваш пример, вы можете установить слот xs
с помощью setf
с помощью средства доступа к слоту, например:
(cl-defstruct stack xs)
(defvar st (make-stack :xs '(1 2 3 4 5)))
(setf (stack-xs st) (cl-map 'list #'1+ (stack-xs st)))
(stack-xs st)
В последней строке выше возвращается '(2 3 4 5 6)
.
Обновление: Недостатком вызова setf
, показанного выше, является то, что средство доступа к слоту необходимо использовать дважды: один раз, чтобы прочитать текущее значение, а затем снова, чтобы обновить его до нового значения. Вы можете использовать cl-callf
для СУШКИ:
(cl-callf (lambda (p) (cl-map 'list #'1+ p)) (stack-xs st))
В качестве альтернативы вы можете заключить вызов setf
в новый метод, определенный для типа stack
, используя cl-defmethod
, возможно, так:
(cl-defmethod stack-update ((s stack) f slot)
"Update SLOT in stack S by applying F.
F is passed one argument, the current value of SLOT,
and is expected to return a new value for SLOT."
(let ((sl (if (keywordp slot) (intern (substring (symbol-name slot) 1)) slot)))
(setf (cl-struct-slot-value 'stack sl s) (funcall f (cl-struct-slot-value 'stack sl s)))))
Затем вы можете позвонить stack-update
следующим образом:
(stack-update st #'(lambda (p) (cl-map 'list #'1+ p)) :xs)
или эквивалентно:
(stack-update st (apply-partially 'cl-map 'list #'1+) 'xs)