常见的Lisp语言:针对defstruct结构体的slot-value

8
在Common Lisp中,我可以使用什么来访问结构体槽位(slot)并使用槽位名称/符号(slot name/symbol)进行操作?
我的要求是:
(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中这是有效的。然而,据我所知,这是非标准行为(相当于C ++中的“未定义行为”)。我不打算切换到另一个CL实现,那么我应该继续使用 slot-value 来处理结构体,还是有更好的方法来处理它?

1个回答

10

通常您会在结构体中使用访问器函数。

您的代码定义了访问器函数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 类,提供元对象协议等。


你可以使用它们。我知道,但是从C++来看,这有点冗长/啰嗦。在C++/C中,您可以通过“.”或“->”访问字段。例如:point p; p.x = 0;。因此,我想要更短的语法。我定义了“->”宏,但发现“slot-value”不应该用于结构体(尽管在许多实现中它可以工作)。这就是为什么我提出了这个问题的原因。 - SigTerm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接