Problem
Given an instance, inst
and a string attr
containing the name of a slot, how can I obtain the value of the slot attr
on inst
?
Of course, if attr
were a symbol rather than a string, I would typically just use (slot-value inst attr)
, but it seems I need the package information to properly call intern
(see below).
Minimal example
(defpackage :pack1
(:use :common-lisp)
(:export :*inst*))
(in-package :pack1)
(defclass temp-class ()
((temp-slot :initarg :temp-slot)))
(defvar *inst* (make-instance 'temp-class :temp-slot "value"))
(defpackage :pack2
(:use :common-lisp :pack1)
(:import-from :pack1 :temp-class))
(in-package :pack2)
(let ((inst *inst*) ; In the real example, inst gets defined outside my control,
; in yet another package
(attr "temp-slot"))
(format t "Given package name: ~S; " ; prints fine
(slot-value inst (intern (string-upcase attr) :pack1)))
(format t "No package name: ~S; " ; signals an error
(slot-value inst (intern (string-upcase attr)))))
Prior art
- From this question, I figured out that my problem was that
intern
was creating symbols in a different package than the one in which the class was defined. - It seems from this question, that I can't extract the package information simply from the instance, so I'll have to figure out another way (besides using
intern
to get there)
Background
I'm working on py-format
a Common Lisp port of
Python's {}
-formatting. To implement the Python .
operator (getattr
) I need to convert the
string following the dot into a slot on the object preceding the dot.