我对lisp很新,所以对可能是一个简单的问题道歉,
虽然我理解DEFVAR和DEFPARAMETER之间的区别(defvar只设置未定义的变量),而LET仅用于本地范围,但是使用SETF而不是之前提到的其他赋值函数是什么?
答案 0 :(得分:5)
DEFVAR和DEFPARAMETER定义并设置全局特殊(动态绑定)变量。
SETF和SETQ设置变量(全局或本地,特殊或词汇),但不定义它们。
SETF具有比SETQ更多的功能,因为它可以设置“位置”(如列表,数组,对象的插槽中的元素......)。
编辑:
保罗说,在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既未声明未绑定。 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
答案 1 :(得分:3)
SETF
会影响现有的绑定或“地点”。您可以使用它更改使用LET
或DEF...
在Common Lisp中,setf
是一个“影响宏的广义位置”。请参阅CLHS 5.1.1 - Overview of Places and Generalized Reference。