lisp,赋值函数的差异

joh*_*hnc 4 lisp common-lisp

我对lisp很新,所以对这可能是一个简单的问题道歉,

虽然我理解DEFVAR和DEFPARAMETER之间的区别(defvar只设置未定义的变量),而LET仅用于本地范围,但是使用SETF而不是之前提到的其他赋值函数是什么?

Rai*_*wig 5

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)