【问题标题】:Why when I create an class can't find-symbol it?为什么当我创建一个类时找不到符号呢?
【发布时间】:2020-09-30 00:12:12
【问题描述】:

我现在对符号感到困惑,我试过了:

CL-USER> (defclass foo2 () ())
#<STANDARD-CLASS COMMON-LISP-USER::FOO2>
CL-USER> (describe 'foo2)
COMMON-LISP-USER::FOO2
  [symbol]

FOO2 names the standard-class #<STANDARD-CLASS COMMON-LISP-USER::FOO2>:
  Direct superclasses: STANDARD-OBJECT
  No subclasses.
  Not yet finalized.
  No direct slots.
; No value
CL-USER> (find-symbol "foo2")
NIL
NIL

为什么我在 find-symbol 函数中找不到“foo2”符号?

我想用这个做什么:

CL-USER> (defun my-make-instance (name n) (make-instance (make-symbol (format nil "~a-~a" name n)))
MY-MAKE-INSTANCE
CL-USER> (my-make-instance "foo" 2)
; Evaluation aborted on #<SB-PCL:CLASS-NOT-FOUND-ERROR foo2 {1003A3A003}>.

我得到:

 There is no class named #:|foo2|. 

我该怎么做?

其他情况:

CL-USER> (describe 'foo2)
COMMON-LISP-USER::FOO2
  [symbol]

FOO2 names the standard-class #<STANDARD-CLASS COMMON-LISP-USER::FOO2>:
  Direct superclasses: STANDARD-OBJECT
  No subclasses.
  Not yet finalized.
  No direct slots.
; No value
CL-USER> (describe (intern "foo2"))
COMMON-LISP-USER::|foo2|
  [symbol]
; No value

为什么会这样? defclass 创建的 "foo2" 是不是内部符号?

【问题讨论】:

    标签: common-lisp symbols


    【解决方案1】:
    • Common Lisp 区分大小写,阅读器会转换大小写;当编译器/解释器读取您的源代码时,它通常会转换为大写。您的示例中不存在名为“foo2”的符号,但名为“FOO2”的符号存在。
    • make-symbol 的调用将返回一个新的符号对象,而不是与您的类关联的符号对象。

    修复代码的最简单方法是将my-make-instance 中的make-symbol 调用替换为对read-from-string 的调用,以获得相同的大小写转换读取器行为以用于您的参数字符串。然后,读者还将在当前包中实习符号,确保它与与您的类关联的符号对象相同。在这种情况下,您可能还想使用defun 而不是defmacro 来定义my-make-instance。 简而言之,您可能需要以下代码:

    (defun my-make-instance (name n)
      (make-instance (read-from-string (format nil "~a-~a" name n))))
    (defclass foo-2 () ())
    (my-make-instance "foo" 2)
    ;returns below instance
    #<FOO-2 {100AB67443}>
    

    【讨论】:

    • 谢谢,用(intern (string-upcase name))解决了。
    【解决方案2】:

    如果你描述符号并得到

    FOO2 命名标准类#&lt;STANDARD-CLASS COMMON-LISP-USER::FOO2&gt;

    那么FOO2在大写字符中确实表示该符号具有大写名称。

    * 'foo2
    FOO2
    

    现在您可以使用函数symbol-name 以字符串形式获取符号名称:

    * (symbol-name 'foo2)
    "FOO2"
    

    正如你在上面看到的,名字是大写的。

    使用大写名称查找符号然后工作:

    * (find-symbol "FOO2")
    FOO2
    :INTERNAL
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      相关资源
      最近更新 更多