5

setf能否与CLHS中的位置和 Norvig 的 PAIP 中的位置相同?

我试图弄清楚 Common Lisp 中的确切位置,但对我来说 HyperSpec 的解释

地点 n. 1. 适合用作一般参考的形式。2.这样一个地方[1]所指的概念位置。

只是帮助有限。

(我知道这不是真正适合的问题,但如果有人知道一篇解释可设置/地点/位置的好文章,我会很感激链接/参考)

4

1 回答 1

14

最初可变数据结构有一个 getter 和一个 setter。car/rplacacdr/的示例rplacd

CL-USER 68 > (let ((a (cons 1 2)))
               (print (list (car a) (cdr a)))
               (rplaca a 'foo)
               (rplacd a 'bar)
               (print (list (car a) (cdr a)))
               (values))

(1 2) 
(FOO BAR) 

在此示例中,getter 是carcdr用于cons 单元格。设置器是rplaca(replace car) 和rplacd(replace cdr)。

每个可变数据结构都有这种情况,通常没有系统的方法可以通过知道 getter 的名称来猜测 setter 的名称。

因此,想法是有一个 getter 和 setter 的注册表。为 getter 注册一个 setter,用户只需知道 getter。setf宏(以及其他类似的incfdecf以及用户定义的宏)然后为使用的 getter 查找 setter。

上面带有setf宏的示例如下所示:

CL-USER 69 > (let ((a (cons 1 2)))
               (print (list (car a) (cdr a)))
               (setf (car a) 'foo)
               (setf (cdr a) 'bar)
               (print (list (car a) (cdr a)))
               (values))

(1 2) 
(FOO BAR) 

如您所见,使用rplacaandrplacd已被setf宏取代。

因此,一个地方基本上是一个注册表格,有一个设置者。为此使用了defsetfdefine-setf-expander

define-modify-macro用来定义一个宏,可以修改一个地方。

例如,我们可以定义一种方法来乘以一个地方的值,类似于incf(增加一个地方)和decf(减少一个地方)。

此功能很旧,最初使用field一词而不是place。因此,能够使用位置的宏以f(字段)结尾。

CL-USER 71 > (define-modify-macro multf (&rest args) 
               * "multiply")
MULTF

CL-USER 72 > (let ((a (cons 1 2)))
               (print (list (car a) (cdr a)))
               (multf (car a) 2)
               (multf (cdr a) 4)
               (print (list (car a) (cdr a)))
               (values))

(1 2) 
(2 8) 
于 2017-04-16T19:37:25.033 回答