gpt4 book ai didi

elisp - 更新结构域

转载 作者:行者123 更新时间:2023-12-05 06:23:20 27 4
gpt4 key购买 nike

在 Elisp 中,是否有更符合人体工学的方法将函数应用于结构中的字段?

假设我有以下内容:

(cl-defstruct stack xs)

(defvar stack (make-stack :xs '(1 2 3 4 5)))

有没有一种简单的方法可以将函数应用于 :xs 字段。我想要这样的 API:

(update-field :xs stack (lambda (xs)
(cl-map 'list #'1+ '(1 2 3 4 5))))

有人知道这是否存在吗?

更新:我正在寻找一种方法来干燥对 (stack-xs stack) 的调用(见下文)。我正在寻找的更类似于 Map.update 之类的东西来自 Elixir 。

(setf (stack-xs stack) (cl-map 'list #'1+ (stack-xs stack)))

最佳答案

cl-defstruct 宏创建 NAME-SLOT 形式的槽访问器,其中 NAME 是结构类型名称, SLOT 是插槽名称。使用您的示例,您可以使用 setf 和插槽访问器来设置 xs 插槽,如下所示:

(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 调用的一个缺点是槽访问器必须使用两次,一次读取当前值,然后再次更新它到新的值(value)。您可以使用 cl-callf 将其擦干:

(cl-callf (lambda (p) (cl-map 'list #'1+ p)) (stack-xs st))

或者,您可以使用 cl-defmethodsetf 调用包装在 stack 类型上定义的新方法中,可能像这样:

(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)

关于elisp - 更新结构域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58438045/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com