假设一个人在一个新的Common Lisp中引入了变量
在REPL和一种类型:(setq q 2)
。
我从这些专栏中了解到这个变量q
是
没有遵循Common Lisp标准和
取决于实施。
我的问题是:最简单的方法或测试是什么 确定它究竟是什么?
我在一个来源中读到q
然后自动被隐式定义
全局动态变量,然后相当于
(defpar q 2)
。
关于这个问题。经验丰富的Lisp 程序员谈论符号表很多。我做 没有找到例如Seibel如何找出其中的内容 那些表。可以访问这些表吗?做 调试器支持以非方式访问这些表 标准方式?
答案 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