common lisp 函数的局部变量只能通过let 或者 函数形参来定义吗

在common lisp 函数里面是不是除了函数形参,要想定义local variable 就得用let来定义

今天发现在defmethod 内部setq的变量在函数外部也能访问到,就有点疑惑了。

刚看了下别人写的工程,好像确实每次defun 下面都会跟一个let 或者 let*

Local variables are introduced with DEFUN, LAMBDA, LET, MULTIPLE-VALUE-BIND and many others.

不要使用setq来定义变量,setq是用来赋值的。

So, if you know what your Common Lisp implementation does, you can use

(setq world (make-new-world))

in the Read-Eval-Print-Loop at the toplevel. But don’t use it in your code, since the effect is not portable. Typically SETQ will set the variable. But some implementation might also declare the variable SPECIAL when it doesn’t know it (CMU Common Lisp does that by default). That’s almost always not what one would want. Use it for casual use if you know what you do, but not for code.

1 个赞

在common lisp cookbook 里面好像很少看见setq 多数都是defparameter defvar setf这几个。今天突然就心血来潮,想用一下,哈哈哈哈.

可以用 &aux 定义。

CL-USER> (defun foo (&aux (x 1) (y 2))
           (+ x y))
FOO
CL-USER> (foo)
3 (2 bits, #x3, #o3, #b11)

也可以这么用

CL-USER> (defun foo (&aux (x 1) (y (+ x 2)))
           (list x y))
FOO
CL-USER> (foo)
(1 3)

现代 Common Lisp 不鼓励用 setq,全部替換成 setf

以多数 CL 的标准,setq 一个 undefined variable 至少是报 warning 的。

3 个赞

我也是尽量用 &aux 以减少因为 let而多一层括号,应该实用吧

我查了下,好像不太建议使用&aux,建议使用的是let啊

来源请求?

common-lisp Tutorial => Auxiliary Variables. 我看的这个

用的少(seldom)不表示不能用。

下次看到deprecated/discouraged 再说不该用。

其实两种我都感觉挺奇怪的,因为别的语言在函数里面定义的变量除非被返回出去的时候还被用这,那生命周期就只到函数结束。外面也访问不到

你用的不是 SBCL 吧,SBCL SETF 未定义变量会直接报错的。老一点的实现为了兼容不用定义变量 MacLisp 才会直接通过。标准里面这是未定义行为。

这就是Lisp/JavaScript 这种函数式语言的精华亮点之一: 闭包(Closure)

C/Java这样就没有,Python 好像有(我没用过)