Lisp和符号表中隐式定义的变量

时间:2016-05-17 12:26:27

标签: common-lisp

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

我从这些专栏中了解到这个变量q是 没有遵循Common Lisp标准和 取决于实施。

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

我在一个来源中读到q然后自动被隐式定义 全局动态变量,然后相当于 (defpar q 2)

关于这个问题。经验丰富的Lisp 程序员谈论符号表很多。我做 没有找到例如Seibel如何找出其中的内容 那些表。可以访问这些表吗?做 调试器支持以非方式访问这些表 标准方式?

1 个答案:

答案 0 :(得分:4)

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

冗长代码段的示例。我正在使用非标准的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