我是 lisp 的新手,所以很抱歉这个问题可能很简单,
虽然我了解 DEFVAR 和 DEFPARAMETER 之间的区别(defvar 仅设置 undefined variable ),并且 LET 仅适用于本地范围,但与前面提到的其他赋值函数相比,SETF 的用途是什么?
最佳答案
DEFVAR 和 DEFPARAMETER 定义和设置全局特殊(动态绑定(bind))变量。
SETF 和 SETQ 设置变量(全局或局部、特殊或词法),但不定义它们。
SETF 比 SETQ 有更多的功能,因为它可以设置“位置”(例如列表中的元素、数组、对象的槽...)。
编辑:
Paul 说在 CLISP 中 SETF 定义了变量。这不完全是它的作用。让我们来看看:
我们有以下程序:
(defun foo (a)
(setf baz (* a a))
a)
(defun bar (a)
(setf baz (* a a))
a)
现在让我们看看如果我们编译该程序,CLISP 会说什么:
[1]> (compile-file "/tmp/test.lisp")
;; Compiling file /tmp/test.lisp ...
WARNING in FOO in lines 2..4 :
BAZ is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING in BAR in lines 6..8 :
BAZ is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
;; Wrote file /tmp/test.fas
0 errors, 2 warnings
在这两个函数中,CLISP 都警告我们变量 BAZ 既未声明也未绑定(bind)。 CLISP 没有拒绝代码,而是将变量 BAZ 视为特殊声明。
如果我们加载并运行代码,情况会改变吗?
[1]> (load "/tmp/test")
;; Loading file /tmp/test.fas ...
;; Loaded file /tmp/test.fas
T
[2]> (foo 2)
2
[3]> (bar 3)
3
[4]> baz
9
[5]> (compile-file "/tmp/test.lisp")
;; Compiling file /tmp/test.lisp ...
WARNING in FOO in lines 2..4 :
BAZ is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING in BAR in lines 6..8 :
BAZ is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
不,即使在执行了 SETF 语句之后,CLISP 仍认为变量 BAZ 未声明。
SBCL 编译器是这样说的:
; in: DEFUN BAR
; (SETF BAZ (* A A))
; ==>
; (SETQ BAZ (* A A))
;
; caught WARNING:
; undefined variable: BAZ
; in: DEFUN FOO
; (SETF BAZ (* A A))
; ==>
; (SETQ BAZ (* A A))
;
; caught WARNING:
; undefined variable: BAZ
LispWorks 编译器是这样说的:
;;;*** Warning in FOO: BAZ assumed special in SETQ
; FOO
;;;*** Warning in BAR: BAZ assumed special in SETQ
; BAR
关于lisp,赋值函数的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2664333/