我对lisp很新,所以对这可能是一个简单的问题道歉,
虽然我理解DEFVAR和DEFPARAMETER之间的区别(defvar只设置未定义的变量),而LET仅用于本地范围,但是使用SETF而不是之前提到的其他赋值函数是什么?
DEFVAR和DEFPARAMETER定义和设置全局特殊(动态绑定)变量.
SETF和SETQ设置变量(全局或本地,特殊或词法),但不定义它们.
SETF具有比SETQ更多的功能,因为它可以设置"位置"(如列表,数组,对象的插槽中的元素......).
编辑:
Paul说,在CLISP SETF中定义变量.这不是它的作用.我们来看一下:
我们有以下计划:
(defun foo (a)
(setf baz (* a a))
a)
(defun bar (a)
(setf baz (* a a))
a)
Run Code Online (Sandbox Code Playgroud)
现在让我们看看如果我们编译该程序,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
Run Code Online (Sandbox Code Playgroud)
在这两个函数中,CLISP警告我们变量BAZ既未声明未绑定.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.
Run Code Online (Sandbox Code Playgroud)
不,即使在执行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
Run Code Online (Sandbox Code Playgroud)
LispWorks编译器有这样的说法:
;;;*** Warning in FOO: BAZ assumed special in SETQ
; FOO
;;;*** Warning in BAR: BAZ assumed special in SETQ
; BAR
Run Code Online (Sandbox Code Playgroud)