常见的lisp:defstruct结构的slot-value

时间:2013-06-22 05:14:27

标签: common-lisp structure accessor clos ccl

在常见的lisp中,我可以使用什么来使用插槽名称/符号来访问结构槽?

我想要的是

(defstruct point (x 0) (y 0))    
(defmacro -> (struct slot) `(slot-value ,struct ,slot))

(setf p (make-point))
(setf (slot-value p 'x) 1)
(setf (-> p 'y) 2)

我正在使用clozure cl,而在clozure cl中这是有效的。但是,AFAIK这是非标准行为(相当于“未定义行为”C ++)。我不打算切换到另一个CL实现,所以我应该继续使用slot-value进行结构,还是有更好的方法来实现它?

1 个答案:

答案 0 :(得分:9)

通常你会使用带有结构的访问器函数。

您的代码定义了访问者函数point-xpoint-y。你可以使用它们。

您还可以在支持它的实现上使用SLOT-VALUE结构。我想这是大多数实现(GCL将是一个例外)。有一个Lisp软件假设SLOT-VALUE适用于结构。我认为实现不会删除对它的支持。它不符合标准,因为某些实现者不希望在已部署的应用程序中提供此功能。

所以两种方式都可以。

如果您想要短名称,请使用访问者:

CL-USER 109 > (defstruct (point :conc-name)
                (x 0) (y 0))
POINT

CL-USER 110 > (make-point :x 5 :y 3)
#S(POINT :X 5 :Y 3)

CL-USER 111 > (setf p1 *)
#S(POINT :X 5 :Y 3)

CL-USER 112 > (x p1)
5

CL-USER 113 > (setf p2 (make-point :x 2 :y 3))
#S(POINT :X 2 :Y 3)

CL-USER 114 > (list p1 p2)
(#S(POINT :X 5 :Y 3) #S(POINT :X 2 :Y 3))

CL-USER 115 > (mapcar 'x (list p1 p2))
(5 2)

然后包必须防止各种访问者函数之间的名称冲突。

如果你想写一个较短版本的SLOT-VALUE,那也没关系。写一个宏。或者写一个内联函数。当然 - 为什么不呢?

正如我所说,SLOT-VALUE适用于大多数实现中的结构。在这种情况下,您不应该关心ANSI CL规范没有定义它。在许多方面,实现扩展了ANSI CL规范。例如,SLOT-VALUE处理结构,将流实现为CLOS类,将条件实现为CLOS类,提供元对象协议,......