CommonLisp函数,用于动态查找包中的绑定

时间:2019-07-04 08:50:41

标签: package common-lisp clos

有没有一种方法可以动态地请求另一个包中的绑定,而动态地我是指不知道某个包中绑定的确切名称。一个具体的例子是:

与程序包B一样,我知道存在一个程序包A,该程序包具有某个类,并且我通过(在LispWorks中)提取该类的所有直接插槽:

(setq direct-slots (mapcar #'slot-definition-name
                           (class-direct-slots (class-of class-in-package-A))))

现在,我想使用MAPCAR将这些插槽绑定到某些值:

(mapcar #'(lambda (slot) (list slot
                               (funcall slot class-in-package-A)))
             direct-slots)

这不起作用,因为我在程序包B中,并且需要程序包精度才能调用(funcall slot class-in-package-A)packageA::slot显然是错误的。是否有为此功能在包装中搜索某个符号?

1 个答案:

答案 0 :(得分:2)

如果您有插槽名称,并且想要获取某个对象中命名插槽的值,请使用slot-value

(mapcar (lambda (slot-name)
          (slot-value some-object slot-name))
        slot-names)

插槽名称是符号,如果您碰巧是在另一个封装中,它们就不会神奇地丢失其封装。我认为您的困惑是您在考虑访问器,但是那是另一回事(内部使用slot-value之类的东西。)

CL-USER> (defpackage #:foo
           (:use #:cl))
#<PACKAGE "FOO">
CL-USER> (defpackage #:bar
           (:use #:cl #:sb-mop))  ; in SBCL
#<PACKAGE "BAR">
CL-USER> (in-package #:foo)
#<PACKAGE "FOO">
FOO> (defclass afoo ()
       ((a :initarg :a)
        (b :initarg :b)))
#<STANDARD-CLASS FOO::AFOO>
FOO> (in-package #:bar)
#<PACKAGE "BAR">
BAR> (mapcar #'slot-definition-name
             (class-direct-slots (find-class 'foo::afoo)))
(FOO::A FOO::B)
BAR> (let ((slot-names (mapcar #'slot-definition-name
                               (class-direct-slots (find-class 'foo::afoo))))
           (obj (make-instance 'foo::afoo
                               :a 1
                               :b 2)))
       (mapcar (lambda (slot-name)
                 (slot-value obj slot-name))
               slot-names))
(1 2)

通常,您应该在“用户”代码中使用访问器,并且应该知道给定对象存在哪些访问器。用户代码是否为直接插槽也无关紧要。