2

I wanted to get the value of an attribute from a pointer, inside another object, but accessing it without evaluating the reference got me the error

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

Here is a piece of code to simulate the error:

(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*)))

After that, evaluating this expression throws an error

(slot-value (car (slot-value *edge-1* 'vertices)) 'pos)

But this one has the desired behavior

(slot-value (eval (car (slot-value *edge-1* 'vertices))) 'pos)

I already know that eval is used for ugly hacks, that's why I'm trying to find a clever way to do what I need.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Gap1512
  • 121
  • 4

1 Answers1

5

When attempting to read the slot's value (slot-value), the slot POS is missing from the object *NODE-1*

*node-1* is not a CLOS instance. It's a symbol. slot-value needs a CLOS instance. Thus trying to compute the slot-value of a symbol makes no sense.

Side note: objects in Common Lisp

In the error message, the term object *NODE-1* means a specific symbol object at runtime. Symbols are objects, too. They are not CLOS objects, that is they are not CLOS instances of a CLOS class. But generally, even a symbol or a string are in Common Lisp considered to be objects.

Why is it a symbol?

You set the vertices slot to be the value of '(*node-1* *node-2*). That's a literal list of two symbols, since you have quoted the list.

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

CL-USER 153 > (mapcar #'type-of *)
(SYMBOL SYMBOL)

One uses objects directly

If you want to compute a list of actual values of those symbols as variables, you need to compute a list of computed values:

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)

The function list creates a fresh list with its arguments as contents.

Getting the value of a symbol: use SYMBOL-VALUE

(symbol-value '*node-1*)
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346