Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 236
johnc Avatar asked Feb 27 '23 04:02

johnc


2 Answers

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
like image 133
Rainer Joswig Avatar answered Mar 03 '23 17:03

Rainer Joswig


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.

like image 24
Doug Currie Avatar answered Mar 03 '23 17:03

Doug Currie