This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Why have the let function when you already have setf?

17 posts · 4679 views

Am I missing something here?

let can define a list of variables and setf can't( as far as I know ). Other than that I see no difference. Is this correct?

Re: Why have the let function when you already have setf?

First of all, let and setf are not functions.
let and setf are completely different things.
setf is a generic assignment operator - it assigns values to "generic places". let is a special form that creates lexical or dynamic variable bindings.

Re: Why have the let function when you already have setf?

Well, you should not create variables with setf (the behavior may vary depending on your implementation, and most of them create global (dynamic) variables). And let is also handy because you can assign a value to some variable and then restore the original value at the end. This is specially good when you have dynamic variables.

Re: Why have the let function when you already have setf?

dmitry_vk wrote:First of all, let and setf are not functions.
let and setf are completely different things.
setf is a generic assignment operator - it assigns values to "generic places". let is a special form that creates lexical or dynamic variable bindings.
I'm not quite grasping the difference yet, but I'm getting there.


Thanks for the replies, they were informative.

Re: Why have the let function when you already have setf?

Setf changes the value of an existing variable (well, it can create new ones, but it isnt supposed to do so) in the current scope, while let creates a new scope and - if necessary - overloads old variable namings by new ones. That is, let doesnt set any variables at all. Formally, you could think of a stack of variable-value-bindings, and let just pushes new ones on that stack, and pops them down again after leaving the let-macro, and the variable-binding being considered by the code is (mostly) the one topmost on this stack.

Let is stateless, while setf explicitly modifies a state. This can make a huge difference for example when working with multiple threads. In general, it is good practice to try to make code stateless, and only introducing states where it is really necessary.
Sorry for my bad english.
Visit my blog http://blog.uxul.de/

Re: Why have the let function when you already have setf?

So each used variable has its own stack of possible bindings?

Re: Why have the let function when you already have setf?

yougene wrote:So each used variable has its own stack of possible bindings?
At least that is one possibility to imagine (and specify) what is being done. I.e., this is the model. The implementation itself is mostly different.
Sorry for my bad english.
Visit my blog http://blog.uxul.de/

Re: Why have the let function when you already have setf?

Let is stateless, while setf explicitly modifies a state. This can make a huge difference for example when working with multiple threads. In general, it is good practice to try to make code stateless, and only introducing states where it is really necessary.
Could you expand on this? Why is let stateless and setf isn't? Why have a variable at all if you're not going to modify it?


Would modifying lists be considered modifying a state?

Re: Why have the let function when you already have setf?

yougene wrote:Could you expand on this? Why is let stateless and setf isn't?
Ok, sorry, "state" is not quite the concept - its about side effects. A let-statement overloads the value of a variable, but does not cause any side effects. See referential transparency for more details on this.
yougene wrote:Why have a variable at all if you're not going to modify it?
It depends on what you mean by "modify". Let overloads bindings of variables for a certain part of the program, without changing the Bindings for anything else. Of course, this modifies what a certain variable name stands for for a clearly defined part of the program code - so it modifies the variable somehow. But it doesnt do anything to the values this variable stands for.
yougene wrote:Would modifying lists be considered modifying a state?
Yes. Modifying a list means modifying a state. But modifying a list means modifying an object, not modifying a variable - i.e. thats something different.
Sorry for my bad english.
Visit my blog http://blog.uxul.de/

Re: Why have the let function when you already have setf?

yougene wrote:Could you expand on this? Why is let stateless and setf isn't? Why have a variable at all if you're not going to modify it?
Perhaps you've completed a long computation and need to use the result multiple times. You don't want to recompute each time you need its value. Or perhaps you've called a function like GET-INTERNAL-REAL-TIME. It's probably very important that this value not change as the function is executed. Maybe you just need to abbreviate.
yougene wrote:Would modifying lists be considered modifying a state?
Yes.

Re: Why have the let function when you already have setf?

Is it possible to use setf without side effects if it's used to only modify variables passed in as parameters or generated within the function?

Is that how you write good lisp code?

Re: Why have the let function when you already have setf?

yougene wrote:Is it possible to use setf without side effects if it's used to only modify variables passed in as parameters or generated within the function?
Have you programmed in other languages? LET is simply one way to define a local (lexically scoped) variable in lisp. In languages like perl, you might say "local x" or "my x". In C/C++/Java, you say "{int x; ...}". In lisp, you use "(let (x) ...)". SETF is the mutation/assignment operator; "(setf x 5)" is like "x=5" in other languages; it does not create a new variable.

Maybe the following snippet will help you.
(defun f (x)
  (setf x 5) ; nobody outside F sees this
  x) ; until this return
(defun g (x)
  (let ((y (+ x 5)))
     (setf x 5)
     y)) ; here, the new value of X is never seen
That LET also shadows dynamic variables is a historical accident. Old lisps (before Scheme) didn't have lexical variables! Instead, there were several interesting schemes for how variables passed values.

Re: Why have the let function when you already have setf?

I understand what let does and what scope is, but thanks for the feedback.

My question was about how to program without side effects. Whether properly programming in lisp is simply a matter of maintaining referential transparency.

Re: Why have the let function when you already have setf?

yougene wrote:Is it possible to use setf without side effects if it's used to only modify variables passed in as parameters or generated within the function?

Is that how you write good lisp code?
You are right, setf will only have side effects if you use it to modify a global variable or a local variable outside of the current function (like, when creating a function, you can modify the values being defined in its surroundings). Sometimes, whether you use setf or let is just a matter of personal preference. For instance when you want your function to accept numbers and strings representing numbers, one way you can do to make sure that the variable holds a number is setf-ing it or rebinding it with let.

In Lisp, we consider setf to be a bad choice when it is not necessary. Lisp is about brevity, not walk on circles around what you are trying to do. In C, programmers often assign the result of a function just to pass it to another function, and they do that when they learn Lisp, which is considered bad Lisp. It is considered to be more Lispy style to nest the function calls, unless the nesting get too haired, in which case you generally use let, but a setf can also be used if it makes sense.

Also, in general, Lispers avoid side effects, but sometimes they are very useful. There are other languages where side effects are condemned with punishment, but that is not the case with Common Lisp ;)

Re: Why have the let function when you already have setf?

Thanks, I think I'm starting to get this functional programming thingamajig.

Re: Why have the let function when you already have setf?

i'm just a newbie too and i don't know if this is considered good style but my functions usually start with a lot of let* bindings with function calls to get their values. this is especially true if i need a value more than once. in the actual function body there are usually only very few calculations going on.

Re: Why have the let function when you already have setf?

hewih wrote:i'm just a newbie too and i don't know if this is considered good style but my functions usually start with a lot of let* bindings with function calls to get their values. this is especially true if i need a value more than once. in the actual function body there are usually only very few calculations going on.
Well, many good libraries do stuff this way, so I think you are safe :)