如何从对象引用中读取插槽而不评估指针

Gap*_*512 2 lisp evaluation symbols list common-lisp

我想从另一个对象内部的指针获取属性的值,但是在不评估引用的情况下访问它会使我出错

When attempting to read the slot's value (slot-value), the slot
POS is missing from the object *NODE-1*.
Run Code Online (Sandbox Code Playgroud)

这是一段模拟错误的代码:

(defclass node ()
  ((pos 
    :initarg :pos
    :initform '(0 0)
    :accessor pos)))

(defclass edge ()
  ((vertices
    :initarg :vertices
    :accessor vertices)))

(defparameter *node-1* (make-instance 'node))
(defparameter *node-2* (make-instance 'node :pos '(100 100)))
(defparameter *edge-1* (make-instance 'edge :vertices '(*node-1* *node-2*)))
Run Code Online (Sandbox Code Playgroud)

之后,评估此表达式将引发错误

(slot-value (car (slot-value *edge-1* 'vertices)) 'pos)
Run Code Online (Sandbox Code Playgroud)

但是这个有预期的行为

(slot-value (eval (car (slot-value *edge-1* 'vertices))) 'pos)
Run Code Online (Sandbox Code Playgroud)

我已经知道它eval可用于丑陋的骇客,这就是为什么我试图找到一种巧妙的方式来做我需要的事情的原因。

Rai*_*wig 5

尝试读取插槽的值(插槽值)时,POS对象中缺少该插槽 *NODE-1*

*node-1*不是CLOS实例。这是一个象征。slot-value需要一个CLOS实例。因此,尝试计算符号的槽值没有任何意义。

旁注:objects在Common Lisp中

在错误消息中,术语“ 对象” *NODE-1*是指运行时的特定符号对象。符号也是对象。它们不是CLOS对象,也就是说,它们不是CLOS类的CLOS实例。但通常在Common Lisp中甚至将符号或字符串也视为对象

为什么是符号?

您将vertices广告位设置为的值'(*node-1* *node-2*)。这是两个符号的文字列表,因为您已经引用了该列表。

CL-USER 152 > '(*node-1* *node-2*)
(*NODE-1* *NODE-2*)

CL-USER 153 > (mapcar #'type-of *)
(SYMBOL SYMBOL)
Run Code Online (Sandbox Code Playgroud)

一个直接使用对象

如果要计算这些符号的实际值作为变量的列表,则需要计算一个计算值的列表:

CL-USER 154 > '((+ 1 2))
((+ 1 2))

CL-USER 155 > (list (+ 1 2))
(3)

CL-USER 160 > (list *node-1* *node-2*)
(#<NODE 402032A2C3> #<NODE 402032B98B>)

CL-USER 161 > (mapcar #'type-of *)
(NODE NODE)
Run Code Online (Sandbox Code Playgroud)

该函数list以其参数作为内容创建一个新列表。

获取符号的值:使用 SYMBOL-VALUE

(symbol-value '*node-1*)
Run Code Online (Sandbox Code Playgroud)