gpt4 book ai didi

common-lisp - 使用 setf 避免冗余位置计算

转载 作者:行者123 更新时间:2023-12-02 07:29:41 26 4
gpt4 key购买 nike

上下文

根据我有限的 Common Lisp 经验,我发现像这样的代码并不罕见

(setf (gethash key table)
(my-transformation (gethash key table)))

从可设置的位置读取数据,对存储在那里的值执行一些计算,然后写入同一位置。我不喜欢的一点是,该地点将被计算两次,但该地点(希望!)两次都是相同的。如果位置计算成本很高,我们要做的工作量是我们需要的两倍。

问题

是否可以消除双重计算的需要?也就是说,是否可以(需要吗?)编写一个宏 setf-inplace:

(setf-inplace (gethash key table) #'my-transformation)

概念上等同于(暂时忽略多值怪异),但可能比原始代码快得多,最好不依赖实现细节?

我知道在这种特殊情况下我可能会本末倒置,因为 SBCL caches the lookup for gethash ,但在我看来,其他可设置的位置,例如(assoc key my-alist),可能不太容易缓存 - 当然,除了通过某些类似于上面的 setf-inplace 的机制。

最佳答案

(setf (gethash key table)
(my-transformation (gethash key table)))

假设转换为1+。那么上面就是

(setf (gethash key table)
(1+ (gethash key table)))

Common Lisp 中有一个宏:

(incf (gethash key table))

Clozure CL 将其扩展为:

(LET* ((#:G69020 KEY)
(#:G69021 TABLE)
(#:G69022 1)
(#:G69019 (+ (GETHASH #:G69020 #:G69021) #:G69022)))
(DECLARE (TYPE BIT #:G69022) (TYPE T #:G69019))
(CCL::PUTHASH #:G69020 #:G69021 #:G69019))

现在请记住,位置的 setter 是在编译时找到的,并且位置的 setter 操作与 getter 不同。 setter 不仅通过更新某些内容来实现不同的操作,而且还可以执行任意其他操作,例如设置事务、获取锁……因此,获取和设置两次不是相同/相似的操作。

Common Lisp 没有表示地点的物理数据结构。位置是一个抽象概念,它将 setter 与给定的 getter 结合在一起。 setter 可以是任意复杂的代码。

那么,在上面的代码中 - 哪些计算是多余的?

您仍然说优化原始情况的访问怎么样:

(incf (car (very-long-access-chain data)))

您必须手写:

(let ((cons-cell (very-long-access-chain data)))
(incf (car cons-cell))

这基本上就是 Lisp 所做的事情。请参阅:CLHS 5.1.1.1 Evaluation of Subforms to Places

关于common-lisp - 使用 setf 避免冗余位置计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22007962/

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