【问题标题】:Accessing an encapsulated class slots within the encapsulating class method in common lisp在通用 lisp 中访问封装类方法中的封装类槽
【发布时间】:2018-01-22 23:04:03
【问题描述】:

我有以下基本类和方法:

        (defgeneric connect-edge (edge))

        (defclass Node ()
          ((forward-edges :initform nil)
           (backward-edges :initform nil)
           (value :initform 0.0)))

        (defclass Edge ()
          ((value :initform 0.0)
           (nodes :initform nil)))

        (defmethod connect-edge ((edge Edge))
        ;; does nothing important. Simplified to cause the problem
            (slot-value (car (slot-value edge 'nodes)) 'forward-edges))

我将方法简化到足以给我一个错误。基本上它在这一点上没有做任何有用的事情,但足以证明问题。

设置

Edge 类具有nodes,它是Node 对象的列表。 Node 类具有Edge 对象的列表。

意图:

读取/写入封装在Edge 对象(节点列表)中的Node 对象中的forward-edgesbackward-edges

问题/疑问:

通过按预期返回 nil 来“工作”:

(defparameter *edge* (make-instance 'Edge))
(setf (slot-value *edge* 'nodes) (list (make-instance 'Node) (make-instance 'Node)))
(connect-edge *edge*)

这段代码给了我下面的错误,为什么

(connect-edge (make-instance 'Edge))

There is no applicable method for the generic function
  #<STANDARD-GENERIC-FUNCTION (SB-PCL::SLOT-ACCESSOR :GLOBAL
                               COMMON-LISP-USER::FORWARD-EDGES
                               SB-PCL::READER) (1)>
when called with arguments
  (NIL).

另外,如果我这样做,我会收到以下错误,我想我明白为什么:没有定义需要 nil 的通用函数:

(connect-edge nil)

There is no applicable method for the generic function
  #<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::CONNECT-EDGE (1)>
when called with arguments
  (NIL).
   [Condition of type SIMPLE-ERROR]

我为什么要这么做?

我有以下代码导致(可能是由于不同的原因)类似的错误:

(defun make-classic (net)
  (loop
     for this-layer in net
     for next-layer in (cdr net)
     do
       (loop
      for this-node in this-layer
      do
        (loop
           for next-node in next-layer
           do
         (let ((edge (make-instance 'Edge)))
           (setf (slot-value edge 'nodes) '(this-node next-node))
           (format t "Type of edge is ~a~%" (type-of edge))
           ;; Error is here
           (connect-edge edge))))))

我不确定错误是否是由于传递了一个作用域变量,所以我最终尝试传递一个(make-instance 'Edge) 来导致错误。

【问题讨论】:

  • 这在很大程度上是不相关的,但通常认为在低级方法之外使用slot-value 是不好的形式(就像在 Java 中使用公共字段是不好的形式一样)。相反,您可以在defclass 期间使用:reader:accessor 参数。除非将阅读器设置为区分大小写(有些人使用诸如&lt;class&gt; 之类的排版约定作为类名),否则对符号使用混合大小写通常也是不习惯的

标签: common-lisp clos


【解决方案1】:

这就是你所需要的:

使用参数调用时 (NIL)。

(slot-value (make-instance 'Edge) 'nodes)

nil,所以

 (slot-value (car (slot-value edge 'nodes)) 'forward-edges))

失败。

【讨论】:

  • 我试过了,但问题是 (slot-value nil 'forward-edges) 给出了不同的错误(对象 NIL 中缺少插槽 FORWARD-EDGES。)。
  • 谢谢。我懂了。我将 '(this-node next-node) 更改为 (list this-node next-node),这就是问题所在。您的回答(和评论)解释了帮助我找到问题的原因。
猜你喜欢
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 2011-09-12
  • 2010-10-13
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多