2014-10-07 10 views
2

Проблема

Дано instance, inst и строку, содержащую attr имя slot, как я могу получить значение слота attr на inst?Как получить доступ к слоту неизвестного экземпляра с помощью строки?

Конечно, если attr были символом, а не строка, я обычно просто использовать (slot-value inst attr), но мне кажется, мне нужна информация о пакете правильно называть intern (см. Ниже)

Пример минимального

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

Предшествующий уровень техники

  • От this question, я понял, что моя проблема в том, что intern создавал символы в другом пакете, чем тот, в котором был определен класс.
  • Кажется, из this question, что я не могу извлечь информацию о пакете просто из экземпляра, поэтому я должен выяснить еще один способ (кроме использования intern попасть)

фон

Я работаю с py-format a Общий Lisp-порт Python's {} -formatting. Чтобы реализовать оператор Python . (getattr) Мне нужно преобразовать строку после точки в слот объекта, предшествующего точке.

ответ

3

Учитывая экземпляр inst и строку attr, содержащую имя слота, как я могу получить значение слота attr на inst?

Слоты не имеют нитей, как названия слотов, а символы. Поскольку имена слотов могут быть произвольными символами, нет общего способа получить значение slot, если все, что у вас есть, - это строка.

CL-USER 124 > (defclass foo() 
       ((s)    ; the slot-name is cl-user::s 
       (system::s)  ; the slot-name is system::s 
       (#:s)))   ; the slot-name is  #:s 
#<STANDARD-CLASS FOO 413054236B> 

Последнее слот-имя является символом без символа. Это не пакет. Таким образом, вы не можете найти его каким-либо образом, если вы его где-то не хранили.

CL-USER 125 > (make-instance 'foo) 
#<FOO 402013F043> 

CL-USER 126 > (describe *) 

#<FOO 402013F043> is a FOO 
S  #<unbound slot> 
S  #<unbound slot> 
S  #<unbound slot> 

Как вы видите выше, у него три слота. Каждый символ имеет имя s, но на самом деле это другой символ.

Вы можете получить имена слотов с помощью интроспекции:

CL-USER 127 > (mapcar #'slot-definition-name 
         (class-direct-slots (find-class 'foo))) 
(S SYSTEM::S #:S) 

Для портативных функций см CLOSER-MOP.

+0

Спасибо - последний бит с интроспекцией поможет мне переосмыслить синтаксис – Felipe

 Смежные вопросы

  • Нет связанных вопросов^_^