【问题标题】:Implicitly defined variables in Lisp and symbol tablesLisp 和符号表中隐式定义的变量
【发布时间】:2016-05-17 12:26:27
【问题描述】:

假设在新的 Common Lisp 中引入变量 在 REPL 和一种类型:(setq q 2)

我从这些列中了解到这个变量 q 是 未按照 Common Lisp 标准定义,并且 取决于实现。

我的问题是:最简单的方法或测试是什么 确定它到底是什么?

我在一个来源中读到 q 然后自动是隐式定义的 全局动态变量,然后等价于 (defpar q 2).

关于这个问题。经验丰富的 Lisp 程序员经常谈论符号表。我愿意 在例如找不到Seibel 如何找出里面有什么 那些桌子。可以访问这些表吗?做 调试器支持以非方式访问这些表 标准方式?

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    使用SETQ 而不是DEFPARAMETER 可能会创建一个全局变量,而不是一个特殊变量。这将在以后引起烦人的调试。不要使用SETQ 来定义变量。

    一个带有冗长代码 sn-ps 的示例。我为此使用了非标准的 SBCL。

    让我们定义一个包含两个变量的包,一个用DEFPARAMETER 定义,一个用SETQ 设置。

    CL-USER> (defpackage :foo (:use :cl))
    #<PACKAGE "FOO">
    CL-USER> (in-package :foo)
    #<PACKAGE "FOO">
    FOO> (defparameter q 2)
    Q
    FOO> (setq w 2)
    ; in: SETQ W
    ;     (SETQ FOO::W 2)
    ; 
    ; caught WARNING:
    ;   undefined variable: W
    ; 
    ; compilation unit finished
    ;   Undefined variable:
    ;     W
    ;   caught 1 WARNING condition
    2 (2 bits, #x2, #o2, #b10)
    FOO> q
    2 (2 bits, #x2, #o2, #b10)
    FOO> w
    2 (2 bits, #x2, #o2, #b10)
    

    警告消息已经告诉我们 SBCL 不喜欢 SETQ 选项,但该变量似乎有效。让我们尝试DESCRIBE变量:

    FOO> (describe 'q)
    FOO::Q
      [symbol]
    
    Q names a special variable:
      Value: 2
    ; No values
    FOO> (describe 'w)
    FOO::W
      [symbol]
    
    W names an undefined variable:
      Value: 2
    ; No values
    

    这表示Q 是一个特殊的变量,而W 是一个未定义的变量。

    FOO> (sb-cltl2:variable-information 'q)
    :SPECIAL
    NIL
    NIL
    FOO> (sb-cltl2:variable-information 'w)
    NIL
    NIL
    NIL
    

    这也证实了W 不是像Q 那样的特殊变量。那么这是什么意思?让我们定义一个使用这些变量的函数:

    FOO> (defun foobar ()
           (format t "~&Q: ~a~%W: ~a~%" q w))
    
    ; in: DEFUN FOOBAR
    ;     (FORMAT T "~&Q: ~a~%W: ~a~%" FOO::Q FOO::W)
    ; 
    ; caught WARNING:
    ;   undefined variable: W
    ; 
    ; compilation unit finished
    ;   Undefined variable:
    ;     W
    ;   caught 1 WARNING condition
    FOOBAR
    FOO> (foobar)
    Q: 2
    W: 2
    NIL
    

    我们再次收到有关W 的警告,但代码似乎仍然有效。让我们尝试隐藏变量。

    FOO> (defun quux ()
           (let ((q 100)
                 (w 100))
             (foobar)))
    ; in: DEFUN QUUX
    ;     (LET ((FOO::Q 100) (FOO::W 100))
    ;       (FOO::FOOBAR))
    ; 
    ; caught STYLE-WARNING:
    ;   The variable W is defined but never used.
    ; 
    ; compilation unit finished
    ;   caught 1 STYLE-WARNING condition
    QUUX
    FOO> (quux)
    Q: 100
    W: 2
    NIL
    

    现在我们注意到,由于W 并不特殊,因此您不能对其进行遮蔽。还有

    FOO> (sb-introspect:who-binds 'q)
    ((QUUX
      . #S(SB-INTROSPECT:DEFINITION-SOURCE
           :PATHNAME NIL
           :FORM-PATH (0 3 2)
           :FORM-NUMBER 0
           :CHARACTER-OFFSET 0
           :FILE-WRITE-DATE NIL
           :PLIST NIL
           :DESCRIPTION NIL)))
    FOO> (sb-introspect:who-binds 'w)
    NIL
    

    我们看不到谁绑定了变量。或者谁设置:

    FOO> (defun qwerty ()
           (setf w 1000
                 q 1000))
    
    ; in: DEFUN QWERTY
    ;     (SETF FOO::W 1000
    ;           FOO::Q 1000)
    ; --> PROGN SETF 
    ; ==>
    ;   (SETQ FOO::W 1000)
    ; 
    ; caught WARNING:
    ;   undefined variable: W
    ; 
    ; compilation unit finished
    ;   Undefined variable:
    ;     W
    ;   caught 1 WARNING condition
    QWERTY
    FOO> (qwerty)
    1000 (10 bits, #x3E8)
    FOO> (sb-introspect:who-sets 'q)
    ((QWERTY
      . #S(SB-INTROSPECT:DEFINITION-SOURCE
           :PATHNAME NIL
           :FORM-PATH (0 3 2)
           :FORM-NUMBER 0
           :CHARACTER-OFFSET 0
           :FILE-WRITE-DATE NIL
           :PLIST NIL
           :DESCRIPTION NIL)))
    FOO> (sb-introspect:who-sets 'w)
    NIL
    

    由于您还询问了符号表,因此查看其中内容的最简单方法是 INSPECT 一个包。您可以使用您的 IDE(在 Slime C-c I 中)或直接调用函数来做到这一点:

    FOO> (inspect (find-package :foo))
    
    The object is a STRUCTURE-OBJECT of type PACKAGE.
    0. %NAME: "FOO"
    1. %NICKNAMES: NIL
    2. %USE-LIST: (#<PACKAGE "COMMON-LISP">)
    3. TABLES: #(#<SB-INT:PACKAGE-HASHTABLE
                   (978+0)/1973 [2.270 words/sym,load=49.6%] {100001A483}>)
    4. MRU-TABLE-INDEX: 0
    5. %USED-BY-LIST: NIL
    6. INTERNAL-SYMBOLS: #<SB-INT:PACKAGE-HASHTABLE (7+0)/17 [2.732 words/sym,load=41.2%] {1006D60AE3}>
    7. EXTERNAL-SYMBOLS: #<SB-INT:PACKAGE-HASHTABLE (0+0)/3 [load=0.0%] {1006D60B13}>
    8. %SHADOWING-SYMBOLS: NIL
    9. DOC-STRING: NIL
    10. LOCK: NIL
    11. %IMPLEMENTATION-PACKAGES: (#<PACKAGE "FOO">)
    12. SOURCE-LOCATION: #S(SB-C:DEFINITION-SOURCE-LOCATION
                            :NAMESTRING NIL
                            :TOPLEVEL-FORM-NUMBER NIL
                            :FORM-NUMBER NIL
                            :PLIST NIL)
    13. %LOCAL-NICKNAMES: NIL
    14. %LOCALLY-NICKNAMED-BY: NIL
    > 6
    
    The object is a STRUCTURE-OBJECT of type SB-INT:PACKAGE-HASHTABLE.
    0. CELLS: #(FOOBAR 0 QUUX ? 0 0 0 E W 0 Q QWERTY 0 0 0 0 0
                #(21 0 98 59 0 0 0 223 135 0 193 37 0 0 0 0 0))
    1. SIZE: 12
    2. FREE: 5
    3. DELETED: 0
    > 0
    
    The object is a VECTOR of length 18.
    0. FOOBAR
    1. 0
    2. QUUX
    3. ?
    4. 0
    5. 0
    6. 0
    7. E
    8. W
    9. 0
    10. Q
    11. QWERTY
    12. 0
    13. 0
    14. 0
    15. 0
    16. 0
    17. #(21 0 98 59 0 0 0 223 135 0 193 37 0 0 0 0 0)
    > 8
    
    The object is a SYMBOL.
    0. Name: "W"
    1. Package: #<PACKAGE "FOO">
    2. Value: 1000
    3. Function: "unbound"
    4. Plist: NIL
    > u
    
    The object is a VECTOR of length 18.
    0. FOOBAR
    1. 0
    2. QUUX
    3. ?
    4. 0
    5. 0
    6. 0
    7. E
    8. W
    9. 0
    10. Q
    11. QWERTY
    12. U
    13. 0
    14. 0
    15. 0
    16. 0
    17. #(21 0 98 59 0 0 0 223 135 0 193 37 201 0 0 0 0)
    > 10
    
    The object is a SYMBOL.
    0. Name: "Q"
    1. Package: #<PACKAGE "FOO">
    2. Value: 1000
    3. Function: "unbound"
    4. Plist: NIL
    > q
    

    您还可以使用DO-SYMBOLS 循环包中的符号。

    FOO> (do-symbols (symbol)
           (when (and (boundp symbol)
                      (eq (symbol-package symbol) *package*))
             (format t "~&~a~%  Value: ~a~%  Info: ~a~%  Who sets: ~a~%  ~
                        Who binds: ~a~%  Plist: ~a~%  Documentation: ~a~%~%"
                     symbol
                     (symbol-value symbol)
                     (multiple-value-list 
                      (sb-cltl2:variable-information symbol))
                     (sb-introspect:who-sets symbol)
                     (sb-introspect:who-binds symbol)
                     (symbol-plist symbol)
                     (documentation symbol 'variable))))
    Q
      Value: 1000
      Info: (SPECIAL NIL NIL)
      Who sets: ((QWERTY
                  . #S(SB-INTROSPECT:DEFINITION-SOURCE
                       :PATHNAME NIL
                       :FORM-PATH (0 3 2)
                       :FORM-NUMBER 0
                       :CHARACTER-OFFSET 0
                       :FILE-WRITE-DATE NIL
                       :PLIST NIL
                       :DESCRIPTION NIL)))
      Who binds: ((QUUX
                   . #S(SB-INTROSPECT:DEFINITION-SOURCE
                        :PATHNAME NIL
                        :FORM-PATH (0 3 2)
                        :FORM-NUMBER 0
                        :CHARACTER-OFFSET 0
                        :FILE-WRITE-DATE NIL
                        :PLIST NIL
                        :DESCRIPTION NIL)))
      Plist: NIL
      Documentation: NIL
    
    W
      Value: 1000
      Info: (NIL NIL NIL)
      Who sets: NIL
      Who binds: NIL
      Plist: NIL
      Documentation: NIL
    

    【讨论】:

    • '可能会创建一个全局变量,而不是一个特殊变量' - 不太可能,但 CMUCL 实际上默认情况下会这样做。
    猜你喜欢
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    相关资源
    最近更新 更多