tags:

views:

175

answers:

2

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 only, what is the is the use of SETF as opposed to the other, previously mentioned assignment functions?

+3  A: 

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.

Doug Currie
So you can't declare a variable with set, thanks
johnc
+2  A: 

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
Rainer Joswig
In CLISP, (setf new-var 5) will define the variable.
Paul Richter
@Paul Richter: what CLISP does is 'undefined' in ANSI Common Lisp and implementation specific. Many implementations will do something similar. Notable is CMUCL, since does something different by default. In the sense of the Common Lisp standard, CLISP will not define the variable. DEFVAR and DEFPARAMETER inform the compiler about the variable and they declare the variable special.
Rainer Joswig