From: Mogens
Subject: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <4826ea26$0$314$157c6196@dreader1.cybercity.dk>
Hi there,

I own the two books "Practical Common Lisp" by Peter Seibel, and "CLtL (2nd ed.)" by Guy L. Steele, Jr.

I don't seem to be able to find out when to use 'let' and 'setf' when assigning variables...

Can somebody, please, explain to me when to use which option?

It may seem trivial to most of you, but as a newbie I have (a little) difficulty in finding my way round all the documentation...

Best wishes,

Mogens

From: ······@gmail.com
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <99fad6f5-4404-40c9-b19c-119f9709b9ff@a1g2000hsb.googlegroups.com>
you should use setf for changing values of already established binding
and that you can do with let/defparameter-defvar (lexical/dynamic)
From: danb
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <0f49ae87-2a88-4f90-96f0-a0c7652a7f7c@d45g2000hsc.googlegroups.com>
On May 11, 7:41 am, Mogens <············@vip.cybercity.dk> wrote:
> I don't seem to be able to find out when to use 'let' and 'setf'
> when assigning variables...
> Can somebody, please, explain to me when to use which option?

As Alex said,
> let (locally) and defvar/defparameter (globally)
> use LET wherever possible, and SETF otherwise :)

There are several different situations to consider.
When you're defining a function, use LET and LET*
to name intermediate values:

(defun variance (xs)
  (let* ((N (length xs))
         (avg (float (/ (reduce #'+ xs) N)))
         (sum (reduce #'+ (mapcar (lambda (x)
                                    (expt (- x avg) 2))
                                  xs))))
    (values (float (/ sum (1- N))) avg)))

Try to avoid using SETF, and try to avoid using global
variables.  If you really need/want to use a global,
you can define it with defvar or defparameter:

(defvar *nums* '(2 6 32 9 0 83 12 4))

Then you can change the value with SETF:

(setf *nums* '(2 6 32 9 -10 0 83 12 -1 4 50))

(variance *nums*) => values 761.6 17.0

You can also use SETF to reassign a local variable that
you defined with LET or LET*, but in many cases, you can
do the same thing without SETF by using mapping functions
like MAPCAR, or iteration forms like DOLIST and DOTIMES,
or by defining your function recursively.

--Dan

------------------------------------------------
Dan Bensen  http://www.prairienet.org/~dsb/

cl-match:  expressive pattern matching in Lisp
http://common-lisp.net/project/cl-match/
From: Robert Maas, http://tinyurl.com/uh3t
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <rem-2008may11-003@yahoo.com>
> From: Mogens <············@vip.cybercity.dk>
> I don't seem to be able to find out when to use 'let' and 'setf'
> when assigning variables...

You're confused. One of temporarily them binds, to a simple
variable only, and then un-binds at the end of the form. The other
assigns, "permanently", into any *place* whatsoever, not just into
a simple variable. They are almost totally different.

(prog (x)
  (format t "x = ~S~%" x) ;prints NIL or () depending on your printer mode
  (setq x 5) ;Setf works the same for simple variables
  (format t "x = ~S~%" x) ;prints 5
  (let ((x 42))
    (format t "x = ~S~%" x) ;prints 42
    (setq x 25)
    (format t "x = ~S~%" x) ;prints 25
    )
  (format t "x = ~S~%" x) ;prints 5
  (setf x 2) ;Setq works the same for simple variables
  (format t "x = ~S~%" x) ;prints 2
  (setq x (list 3 5 7)) ;Setf works the same for simple variables
  (format t "x = ~S~%" x) ;prints (3 5 7)
  (setf (cadr x) 42) ;Setq can't be used here
  (format t "x = ~S~%" x) ;prints (3 42 7)
  (setf (cdddr x) 99) ;Setq can't be used here
  (format t "x = ~S~%" x) ;prints (3 42 7 . 99)
  )

15TH MODEM DROPPAGE TODAY AT 14:28, SINCE FIRST LOGIN TODAY AT 10:49.
MEAN TIME BETWEEN FAILURE <14 MINUTES.

Note that lexical closures
 (what you get when you put function around a lambda expression,
  when the whole thing is inside some other form that has a lexical
  binding; also what you get when you execute a DEFUN form inside a
  form that has a lexical binding)
allow you to capture the current binding and save it away for
permanent use. Here's a demo of that, using DEFUNs:

(prog (x)
  (defun bind1a-getx () x)
  (setq x 2)
  (defun bind1b-getx () x)
  (let ((x 3))
    (defun bind2a-getx () x)
    (setq x 5)
    (defun bind2b-getx () x)
    )
  (setq x 4)
  (defun bind1c-getx () x)
  (let ((x 86))
    (defun bind3a-getx () x)
    (setq x 99)
    (defun bind3b-getx () x)
    )
  (setq x 6)
  (defun bind1d-getx () x)
  )
Converted BIND1A-GETX.
Converted BIND1B-GETX.
Converted BIND2A-GETX.
Converted BIND2B-GETX.
Converted BIND1C-GETX.
Converted BIND3A-GETX.
Converted BIND3B-GETX.
Converted BIND1D-GETX.
;The JIT compiler in CMUCL is telling me it converted what looks
; like just a DEFUN into a lexical closure.

(list (bind1a-getx) (bind1b-getx)
      (bind2a-getx) (bind2b-getx)
      (bind1c-getx)
      (bind3a-getx) (bind3b-getx)
      (bind1d-getx)
      )
+> (6 6 5 5 6 99 99 6)

Note there are only three lexical bindings (each converted to a
lexical-closure binding): The toplevel binding in the PROG, the
re-binding in the first LET, and the other re-binding in the second
LET. The toplevel binding was NIL then permanently changed to 2
then permanently changed to 4 then permanently changed to 6. All
four functions BIND1*-GETX see that same lexical binding, so all
four see the final value of 6 at the time they are actually called
much later during the evaluation of parameters to the LIST
function. If they had ever been called before that binding was
changed to 6, they would have returned whatever the binding was at
*that* moment. Likewise both functions defined within the first LET
see that first-LET binding, which was 3 but changed to 5, and when
called each is getting the *current* value of that same binding,
which is 5. Ditto for second-LET binding which was 86 but changed
to 99, so 99 seen at time of call.

> Can somebody, please, explain to me when to use which option?

Use LET when you want to temporarily set up a *new* binding, to
override *temporarily* whatever might have been bound with the same
name at a higher level, or might not have been bound at all
previously.

Use SETQ or SETF when you want to *change* a binding, or global,
which is *already* in effect, so that *same* binding will
henceforth show the new value instead of the old value.
(I prefer SETQ for such use, so I can find simple variable
 assignments by string search in text editor without having to see
 SETFs of structure modifications mixed in with them.)

Use SETF (not SETQ) when you want to change a place within a
structure, such as a CAR or CDR of a CONS cell, or an element of an
array, or a character of a string, or a value associated with a key
in a hash table, etc. etc. etc.

> It may seem trivial to most of you, but as a newbie I have (a
> little) difficulty in finding my way round all the documentation...

You need to understand the difference between a binding of a symbol
(to establish a place where a value can be held) and the value
which is in that place. You need to understand the difference
between making a new binding (which doesn't affect any old binding
except to temporarily hide it) and changing the value within an
already-existing binding to have a different value from what that
*same* binding had before.
I hope my examples above have helped your understanding of these concepts.

If you ever programmed in C or Java:
LET is like declaring a new variable within a new block.
SETQ/SETF is like an assignment statement.
  {int x=3; /* outer binding, value initially 3 */
   x = 5; /* outer binding, changed value to 5 */
     {int x=40; /* inner binding temporarily hiding the outer binding */
      printf("%d",x); /* prints value of inner binding, currently 40 */
      x = 42; /* inner binding, changed value */
      printf("%d",x); /* prints value of inner binding, currently 42 */
     }       /* end of inner binding. Below here outer binding visible again */
   printf("%d",x); /* prints value of outer binding, still 5 */
  }
Pardon any syntactic mistakes in the C. I haven't tested it, too
much trouble to create a file with main and compile it and run it.
Lisp is so much easier to test code fragments directly in REP.

16TH MODEM DROPPAGE TODAY AT 15:05, SINCE FIRST LOGIN TODAY AT 10:49.
REDIAL FAILED BECAUSE PHONE LINE BUSY, RE-DIALED AGAIN AT 15:05.
MEAN TIME BETWEEN FAILURE 16 MINUTES, NOT COUNTING SEVERAL BUSY
LINES, AND NOT COUNTING WHEN I WAS SO BUSY EDITING THAT I DIDN'T
NOTICE RIGHT AWAY THAT THE MODEM HAD LOST CARRIER.
From: Alex Mizrahi
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <4826f278$0$90270$14726298@news.sunsite.dk>
 M> I own the two books "Practical Common Lisp" by Peter Seibel, and "CLtL
 M> (2nd ed.)" by Guy L. Steele, Jr.

 M> I don't seem to be able to find out when to use 'let' and 'setf' when
 M> assigning variables...

let (locally) and defvar/defparameter (globally) create variable binding --  
they associate variable name with place where its value is stored.
setf can only change value of existing variable that is created either via 
LET, or via defvar/defparameter.

 M> Can somebody, please, explain to me when to use which option?

use LET wherever possible, and SETF otherwise :)
changes made by LET are always contained within the body of LET, while 
changes by SETF persist.
so it's generally believed that LET makes programs easier to maintain.

however, SETF is, basically, the only option if you need to change a part of 
some compound structure -- array, hash-table, string, object or whatever. 
From: Ken Tilton
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <48275d7c$0$15190$607ed4bc@cv.net>
Mogens wrote:
> Hi there,
> 
> I own the two books "Practical Common Lisp" by Peter Seibel, and "CLtL (2nd ed.)" by Guy L. Steele, Jr.
> 
> I don't seem to be able to find out when to use 'let' and 'setf' when assigning variables...

As rarely as possible. SETF is a sin against humanity, LET is ok but 
please keep the blinds drawn and if you had the freely downloadable PDF 
of "On Lisp" you would know there is a tax on it.

> 
> Can somebody, please, explain to me when to use which option?

Er, rarely? btw, what are you going to SETF if you have not established 
a variable with LET. Omigod. Not a global?!

> 
> It may seem trivial to most of you,...

I was thinking "imperative" vs. "functional". If you get the latter 
going you will not even be asking the question, ie, it is not trivial, 
it is off-topic for good lisp programming style discussions.

You might post some Actual Code if you disagree -- perhaps you do have a 
need for SETF (the hardest to justify).

  but as a newbie I have (a little) difficulty in finding my way round 
all the documentation...

ROFL. See my recent "Why Wasn't I told?" thread to learn the bad news: 
the difficulty never ends, Pitman cocked up the documentation.

hth, kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/
ECLM rant: 
http://video.google.com/videoplay?docid=-1331906677993764413&hl=en
ECLM talk: 
http://video.google.com/videoplay?docid=-9173722505157942928&q=&hl=en
From: MasterZiv
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <be7af296-2366-416d-b942-612d550a8bce@e53g2000hsa.googlegroups.com>
On 11 ÍÁÊ, 16:41, Mogens <············@vip.cybercity.dk> wrote:

> I don't seem to be able to find out when to use 'let' and 'setf' when assigning variables...

If you know some other programming languages, you may use an analogue
like

-- when you need to DECLARE a variable, you usually use LET
-- when you need to ASSIGN a value to a vriable which already has been
declared, you usually use SETF (or SETQ, or SET or some other
derivative).

This is for sure NOT the strict rule, but a good first approximation.
From: Chris Barts
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <87hcd3qi3k.fsf@chbarts.motzarella.org>
MasterZiv <·········@gmail.com> writes:

> On 11 май, 16:41, Mogens <············@vip.cybercity.dk> wrote:
>
>> I don't seem to be able to find out when to use 'let' and 'setf'
>> when assigning variables...
>
> If you know some other programming languages, you may use an
>analogue like
>
> -- when you need to DECLARE a variable, you usually use LET

No. This doesn't work in multiple ways:

* It doesn't help you with global variables unless you deform your
  code. DEFPARAMETER is what you want for globals.

* It doesn't tell the compiler what type the variable is. Most of the
  time it isn't important anyway, but declaration in most common
  languages implies you giving type information to the
  compiler. DECLARE does that.

> -- when you need to ASSIGN a value to a vriable which already has been
> declared, you usually use SETF (or SETQ, or SET or some other
> derivative).

Forget SETQ and SET even exist. They're embarrassing relics of a bygone
age (especially SET). SETF is the only thing you need to know.

>
> This is for sure NOT the strict rule, but a good first approximation.

It isn't even that.
From: Alex Mizrahi
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <482979fd$0$90271$14726298@news.sunsite.dk>
 CB> Forget SETQ and SET even exist. They're embarrassing relics of a bygone
 CB> age (especially SET).

nah, SET is cool:

(defun initialize-user-parameters ()
  (loop for (keyword variable) in *user-configurable-parameters* do
       (awhen (get-user-configuration-parameter keyword)
          (set variable it))))
From: Edi Weitz
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <uod7a4f2l.fsf@agharta.de>
On Tue, 13 May 2008 14:22:32 +0300, "Alex Mizrahi" <········@users.sourceforge.net> wrote:

> nah, SET is cool:
>
> (defun initialize-user-parameters ()
>   (loop for (keyword variable) in *user-configurable-parameters* do
>        (awhen (get-user-configuration-parameter keyword)
>           (set variable it))))

  (setf (symbol-value variable) it)

would have exactly the same effect.

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Alex Mizrahi
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <4829937b$0$90262$14726298@news.sunsite.dk>
 ??>> nah, SET is cool:
 ??>>
 ??>> (defun initialize-user-parameters ()
 ??>>   (loop for (keyword variable) in *user-configurable-parameters* do
 ??>>        (awhen (get-user-configuration-parameter keyword)
 ??>>           (set variable it))))

 EW>   (setf (symbol-value variable) it)

 EW> would have exactly the same effect.

sure. but SET is cool. 
From: Pascal J. Bourguignon
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <7chcd22v6y.fsf@pbourguignon.anevia.com>
Mogens <············@vip.cybercity.dk> writes:

> Hi there,
>
> I own the two books "Practical Common Lisp" by Peter Seibel, and "CLtL (2nd ed.)" by Guy L. Steele, Jr.
>
> I don't seem to be able to find out when to use 'let' and 'setf' when assigning variables...
>
> Can somebody, please, explain to me when to use which option?

LET doesn't assign variables, it creates them, if needed.  Yep, sometimes it doesn't even create variables:


C/USER[4]> (disassemble (lambda (y) (let ((x (* y y))) (+ x 1))))

Disassembly of function :LAMBDA
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
6 byte-code instructions:
0     (LOAD&PUSH 1)
1     (LOAD&PUSH 2)
2     (CALLSR&PUSH 2 55)                  ; *   
5     (LOAD&PUSH 0)
6     (CALLS2 151)                        ; 1+
8     (SKIP&RET 3)
NIL

In this first function, LET didn't create any variable for X.  It actually compiled:

   (lambda (y) (+ (* y y) 1))



C/USER[5]> (disassemble (lambda (y) (let ((x (* y y))) (f (lambda () x)))))
WARNING in LAMBDA :
Function F is not defined

Disassembly of function :LAMBDA
(CONST 0) = #<COMPILED-FUNCTION :LAMBDA-1>
(CONST 1) = F
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
10 byte-code instructions:
0     (NIL)
1     (MAKE-VECTOR1&PUSH 1)
3     (LOAD&PUSH 2)
4     (LOAD&PUSH 3)
5     (CALLSR 2 55)                       ; *
8     (STOREC 0 0)                                ;; <--- Store the product in the variable X
11    (LOAD&PUSH 0)
12    (COPY-CLOSURE&PUSH 0 1)             ; #<COMPILED-FUNCTION :LAMBDA-1>
15    (CALL1 1)                           ; F
17    (SKIP&RET 3)
NIL
C/USER[6]> 


On the other other in this second function, LET did create a variable.



> It may seem trivial to most of you, but as a newbie I have (a little) difficulty in finding my way round all the documentation...

If possible, prefer LET over SETF.  

(defun f (x)
  (let ((square (* x x)))
    (let ((and-more (+ square 2)))
      (let ((result (< and-more 10)))
         result))))

is much, much better than:

(defun f (x)
  (setf x (* x x))
  (setf x (+ x 2))
  (setf x (< x 10))  ; actually this is very bad.
  x)


since with LET you can give names to subexpressions (thus making the
code clearer), and you avoid modifying the memory, therefore spending
less energy, this is good for your ecologic kharma, and also it makes
proving the program easier than with assignment.
  
-- 
__Pascal Bourguignon__
From: Mikael Jansson
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <a4dbfd6f-d8e8-4828-b9d4-4b8f1f45896b@y21g2000hsf.googlegroups.com>
On May 13, 3:24 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Mogens <············@vip.cybercity.dk> writes:
> > Hi there,
>
> > I own the two books "Practical Common Lisp" by Peter Seibel, and "CLtL (2nd ed.)" by Guy L. Steele, Jr.
>
> > I don't seem to be able to find out when to use 'let' and 'setf' when assigning variables...
>
> > Can somebody, please, explain to me when to use which option?
>
I used to be a bit confused too, before.  If you come from a C
background, you can think of variables introduced in a LET environment
as the local variables of a function (that's usually where you do LET
bindings).  Occasionally, you want to change the value of the LET-
bound variable. Use SETF then.

The second case is when you have a resource that's shared by many
functions, and you don't want to (for some reason) pass it around to
all functions you call. Or a variable that's going to be used by other
libraries.  You would then use a special variable, which are declared
toplevel with (defparameter *foo* whatever-value-you-want-it-to-be) or
(defvar *bar* some-other-value).  Important thing to know here is that
evaluating a (defvar ...) form will only change the value the /first/
time it's evaluated; (defparameter ...) will change it each time.  To
change a variable introduced by (defvar ...), you'll need to SETF it.

>
> > It may seem trivial to most of you, but as a newbie I have (a little) difficulty in finding my way round all the documentation...
>
> If possible, prefer LET over SETF.  
>
> (defun f (x)
>   (let ((square (* x x)))
>     (let ((and-more (+ square 2)))
>       (let ((result (< and-more 10)))
>          result))))
>
What's the reason for not using LET* here?

--
Mikael Jansson
http://mikael.jansson.be
From: Pascal J. Bourguignon
Subject: Re: Newbie: When to use 'let' and 'setf' in CL?
Date: 
Message-ID: <7cfxsj27n8.fsf@pbourguignon.anevia.com>
Mikael Jansson <··············@gmail.com> writes:

> On May 13, 3:24�pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> If possible, prefer LET over SETF. �
>>
>> (defun f (x)
>> � (let ((square (* x x)))
>> � � (let ((and-more (+ square 2)))
>> � � � (let ((result (< and-more 10)))
>> � � � � �result))))
>>
> What's the reason for not using LET* here?

Pedagogical. We were discussing LET vs. SETF, not LET vs. LET*.

-- 
__Pascal Bourguignon__