所以,我从setq and defvar in lisp,http://www.cs.ucf.edu/courses/cop4020/spr2006/plsetup.html和In Lisp, how do I fix "Warning: Assumed Special?"等地方阅读了有关setf和defvar之间的区别。 所以我决定尝试一下这个想法:
CL-USER> (defun foo ()
(setf x 10)
(print x))
; in: DEFUN FOO
; (SETF X 10)
; ==>
; (SETQ X 10)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
FOO
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {10040F1543}>.
CL-USER> (foo)
10
10
CL-USER> x
10
好的,我知道setf应该用于更改现有变量的值,但在SBCL中未定义的变量警告似乎处理得相当不错(尽管我已经阅读过不同的CL实现可能会以不同的方式处理这个问题,因此这并不是最好的做法)。
进入第二个测试:
CL-USER> (defun bar ()
(defvar y 15)
(print y))
; in: DEFUN BAR
; (PRINT Y)
;
; caught WARNING:
; undefined variable: Y
;
; compilation unit finished
; Undefined variable:
; Y
; caught 1 WARNING condition
BAR
CL-USER> y
; Evaluation aborted on #<UNBOUND-VARIABLE Y {10045033D3}>.
CL-USER> (bar)
15
15
CL-USER> y
15
根据链接,我将setf更改为defvar,我认为这应该可以同时创建和绑定变量。现在我的未定义变量警告被推到(print y)行...这是怎么回事?
作为一个次要的问题,我期望任何在函数内分配的变量的值都无法在函数外部访问,就像Python中的情况一样:
>>> def foo():
... x = 10
... print x
...
>>> foo()
10
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
我猜这与common lisp处理作用域的方式有关,即defvar会创建一个“全局特殊变量”...所以我最后尝试了一次使用(let ...)。
CL-USER> (defun baz () (let ((z 10)) (print z)) (incf z 10) (print z))
; in: DEFUN BAZ
; (INCF Z 10)
; --> LET*
; ==>
; (SETQ Z #:NEW0)
;
; caught WARNING:
; undefined variable: Z
;
; compilation unit finished
; Undefined variable:
; Z
; caught 1 WARNING condition
在阅读了defvar、defparameter、setf和setq有什么区别之后,以下代码似乎可以正常工作:
CL-USER> (defun apple ()
(defparameter x 10)
(print 10))
APPLE
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {1004436993}>.
CL-USER> (apple)
10
10
CL-USER> x
10
再次重申我的问题:
1)setf,defvar和let是什么?
2)是否有一种方法可以使common lisp在函数内部作用域像python示例中那样?
&aux
,总是使用let
。 - Vatine&aux
几乎没有被使用,而let
则很常见。同时,有一个比函数更小的 let 也并不少见。 - Samuel Edwin Ward