lisp, differences in assignment functions
I'm pretty new to lisp, so apologies for what may be a simple question,
Whilst I understand the difference between DEFVAR and DEFPARAMETER (defvar only sets undefined variables), and the LET is for local scope on开发者_如何转开发ly, what is the is the use of SETF as opposed to the other, previously mentioned assignment functions?
DEFVAR and DEFPARAMETER define and set global special (dynamically bound) variables.
SETF and SETQ set variables (global or local, special or lexical), but don't define them.
SETF has more capabilities than SETQ, since it can set 'places' (like elements in lists, arrays, object's slots, ...).
Edit:
Paul says that in CLISP SETF defines the variable. That's not quite what it does. Let's have a look:
We have the following program:
(defun foo (a)
(setf baz (* a a))
a)
(defun bar (a)
(setf baz (* a a))
a)
Now let's see what CLISP says if we compile that program:
[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
In both functions CLISP warns us that the variable BAZ is neither declared not bound. Instead of rejecting the code, CLISP treats the variable BAZ as it were declared special.
Does that change if we load and run the code?
[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.
Nope, even after executing the SETF statements, CLISP thinks that the variable BAZ is not declared.
The SBCL compiler has this to say:
; 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
The LispWorks compiler has this to say:
;;;*** Warning in FOO: BAZ assumed special in SETQ
; FOO
;;;*** Warning in BAR: BAZ assumed special in SETQ
; BAR
SETF
affects an existing binding or "place." You can use it to change the value of any of the things you created with LET
or DEF...
In Common Lisp, setf
is a "generalized place affecting macro." See CLHS 5.1.1 - Overview of Places and Generalized Reference.
精彩评论