Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Assistance Needed: Setf

18 views
Skip to first unread message

Alden L. Pierre

unread,
Oct 20, 2006, 9:19:01 AM10/20/06
to
Hello,

I'm in the process of teaching myself clisp. I'm using Paul Graham Ansi
Common Lisp book. While reading this book I've stumble upon sections,
which I currently don't understand fully.

setf:

1. It's been mentioned to avoid using setf and things like it.

I understand this expression (setf x (list 'a 'b 'c))
x is a set which contains ABC.

How ever I don't understand this expression fully:
(setf (car x) 'n) how is it that x contains NBC? I know the car function
will return a complete list minus the first element. Also N is to be
placed in a new a variable, in this case it's the list, how is it that x
now contains NBC? I'm trying to understand how the expression gets
evaluated and why did the x variable get modified?

Regards
Alden

Peder O. Klingenberg

unread,
Oct 20, 2006, 9:49:32 AM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> 1. It's been mentioned to avoid using setf and things like it.

Well, only if you are trying to program in a functional style, then
you would try to avoid assignments. Otherwise, setf is a perfectly
usable assignment operator.

> I understand this expression (setf x (list 'a 'b 'c))
> x is a set which contains ABC.

It could be viewed that way. It could also be viewed as a list of
three elements: the symbols A B and C.

> How ever I don't understand this expression fully:
> (setf (car x) 'n) how is it that x contains NBC?

Because (car x) names a "place" (something assignable, similar to an
lvalue in algol-based languages), namely the first element of the list
held in X.

> I know the car function will return a complete list minus the first
> element.

You are thinking of CDR.

> Also N is to be placed in a new a variable, in this case it's the
> list, how is it that x now contains NBC?

N is to be placed in the place named by the first argument to the
SETF, that is, the first element of X.

> I'm trying to understand how the expression gets evaluated and why
> did the x variable get modified?

What did you expect to happen?

If you had used CDR instead of CAR, that would also be an assignable
place, and you would still have modified X. That is:

(setf (cdr x) 'n) => (A . N)
X => (A . N)

(Never mind the dot in the results for now.)

Basically, with both (car x) and (cdr x) as first arguments to setf,
you are identifying parts of the structure helt by X which you want to
modify.

If you tell us what you wanted to accomplish, we can probably tell you
how to do it.

...Peder...
--
Sløv uten dop.

Pascal Bourguignon

unread,
Oct 20, 2006, 10:09:41 AM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> Hello,
>
> I'm in the process of teaching myself clisp. I'm using Paul Graham
> Ansi Common Lisp book. While reading this book I've stumble upon
> sections, which I currently don't understand fully.
>
> setf:
>
> 1. It's been mentioned to avoid using setf and things like it.

What?

On the contrary, nowadays everybody use setf for everything. I mean,
vs. SET or SETQ.

Of course, if you can write functionnaly instead of imperatively, it's
better to use LET, LET* and LAMBDA than SETF.


> I understand this expression (setf x (list 'a 'b 'c))
> x is a set which contains ABC.

No.

X is a symbol.

Assuming X names a variable (eg. declared with LET or DEFVAR),

(setf x (list 'a 'b 'c))

will BIND the variable X with the value obtained from the evaluation
of (list 'a 'b 'c). This will be a cons cell, whose car is the symbol
A and whose cdr is another cons cell, whose car is the symbol B and
whose cdr is anoter cons cell, whose car is the symbol C and whose cdr
is the symbol NIL. Said otherwise, a list containing the symbols A, B,
and C. Not a set containing a symbol ABC.

> How ever I don't understand this expression fully:
> (setf (car x) 'n) how is it that x contains NBC?

X doesn't contain NBC.

X is still a symbol bound to the same list.

But the car of this list, that is, the car of the cons cell bound to
X, will be changed to contain the symbol N instead of the symbol A.

Therefore, that same list will now contain the symbols N, B and C.

The symbol NBC is entirely unrelevant to this discussion, as was the
symbol ABC. I've got no idea how you could come up with these symbols.


> I know the car
> function will return a complete list minus the first element.

You know strange things. Are you from a parallel universe?


> Also N
> is to be placed in a new a variable, in this case it's the list, how
> is it that x now contains NBC?

A symbol like X doesn't contain anything.


> I'm trying to understand how the
> expression gets evaluated and why did the x variable get modified?

The variable named X isn't modified at all by (setf (car x) ...)
It's the car of the cons cell bound to the symbol X that is modified.

(setf x ...) modifies the binding of the symbol X.
(setf (car x) ...) modifies the car of the cons cell bound to X.

In Lisp, when we want to say blue, we say blue, we don't say red.

After (SETF X (LIST 'A 'B 'C)):
+-----------------------------------+
| X-+ |
| | |
| v |
| +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| v v v |
| +---+ +---+ +---+ |
| | A | | B | | C | |
| +---+ +---+ +---+ |
+-----------------------------------+

After (SETF (CAR X) 'N):
+-----------------------------------+
| X-+ |
| | |
| v |
| +---+---+ +---+---+ +---+---+ |
| | *น| * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| v v v |
| +---+ +---+ +---+ +---+ |
| | N | | A | | B | | C | |
| +---+ +---+ +---+ +---+ |
+-----------------------------------+

Only the pointer marked น is modified.

--
__Pascal Bourguignon__ http://www.informatimago.com/

WARNING: This product warps space and time in its vicinity.

Alden L. Pierre

unread,
Oct 20, 2006, 10:40:04 AM10/20/06
to
Peder O. Klingenberg wrote:
> You are thinking of CDR.
>
Yes, your right. So much information for such a small book.

>> Also N is to be placed in a new a variable, in this case it's the
>> list, how is it that x now contains NBC?
>
> N is to be placed in the place named by the first argument to the
> SETF, that is, the first element of X.
>
>> I'm trying to understand how the expression gets evaluated and why
>> did the x variable get modified?
>
> What did you expect to happen?

When I see (setf (car x) 'n) here is how it breaks down in my mind:

1. 'n gets evaluated and returns N.
2. (car x) gets evaluated and returns the first element in the set x.
3. Now we are going to combine steps 1 and 2.
4.( setf steps1 steps2 )

Naturally setf needs a place and value. In this case the place is x and
the value is n.

I think I've got it. Please correct me if I'm wrong. When setf begins to
do it's evaluation here are the things that will take place, again this
is how I process the information:

1. take the value, in this case 'n
2. now because (car x) returns the first element of our set, switch that
with 'n.
3. 'n is now in the set x, because setf needs a place to assign a value
by definition. When (car x) gets evaluated we are referring to
"place" as the first element of the set x.

> If you tell us what you wanted to accomplish, we can probably tell you
> how to do it.
>

I just wanted to get an understand of the expression which was presented
in chapter 2 page 21 of Paul Graham book that I'm using.

What was throwing me off was (car x) being combined with setf. (car x)
by itself will return the first element in set x without modifying x.


Regards,
Alden

Ken Tilton

unread,
Oct 20, 2006, 11:04:56 AM10/20/06
to

It /is/ unusual to see what looks like a reading function used as a
place suitable for a write, but that is just a nice bit of Lisp
syntactic sugar.

If you look up CAR in the hyperspec, you will see it described as an
"accessor". That means you can read or write with it. If it were (just)
a "function", you would not be able to setf it.

(defun my-car (x) (car x))

(my-car '(42)) -> 42

(let ((x (list 42))) (setf (my-car x) 3)) -> error

And now the fun bit:

(defun (setf my-car) (new-car cell)
(setf (car cell) new-car))

(let ((x (list 42))) (setf (my-car x) 3)) -> 3


The nice thing is that I can now also:

(setf (my-car (big-fn-returning-a-cons 'left 'right 'indiff)) 42)
-> 42 (in whatever cons that was returned by big-fn).

So now I can use a simple list as a datastructure where each element has
certain semantics associated with that position, and instead of having a
bunch of source full of nth this and nth that I can define accessors to
make my code more readable and make refactoring easier.

kt

--
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
-- Smiling husband to scowling wife, New Yorker cartoon

Ken Tilton

unread,
Oct 20, 2006, 11:24:18 AM10/20/06
to

By which I mean, you can use (setf (car ....) ...) syntax, which is not
automatically the case just because one has a function that returns the
value from a place, as I went on to discuss...

.... If it were (just)


> a "function", you would not be able to setf it.
>
> (defun my-car (x) (car x))
>
> (my-car '(42)) -> 42
>
> (let ((x (list 42))) (setf (my-car x) 3)) -> error
>
> And now the fun bit:
>
> (defun (setf my-car) (new-car cell)
> (setf (car cell) new-car))
>
> (let ((x (list 42))) (setf (my-car x) 3)) -> 3

...and (print x) would -> (3)

kt

Pascal Bourguignon

unread,
Oct 20, 2006, 11:28:36 AM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:
> When I see (setf (car x) 'n) here is how it breaks down in my mind:
>
> 1. 'n gets evaluated and returns N.
> 2. (car x) gets evaluated and returns the first element in the set x.
> 3. Now we are going to combine steps 1 and 2.
> 4.( setf steps1 steps2 )

You should send us a postcard from your fantasy world.
It sounds interesting!


>> If you tell us what you wanted to accomplish, we can probably tell you
>> how to do it.
>
> I just wanted to get an understand of the expression which was
> presented in chapter 2 page 21 of Paul Graham book that I'm using.

Try: http//www.lispworks.com/documentation/HyperSpec/Body/03_a.htm
and in particular:
http://www.lispworks.com/documentation/HyperSpec/Body/03_abab.htm

--
__Pascal Bourguignon__ http://www.informatimago.com/

The mighty hunter
Returns with gifts of plump birds,
Your foot just squashed one.

Pascal Bourguignon

unread,
Oct 20, 2006, 11:32:12 AM10/20/06
to
Ken Tilton <kent...@gmail.com> writes:
> It /is/ unusual to see what looks like a reading function used as a
> place suitable for a write, but that is just a nice bit of Lisp
> syntactic sugar.
>
> If you look up CAR in the hyperspec, you will see it described as an
> "accessor". That means you can read or write with it. If it were
> (just) a "function", you would not be able to setf it.
>
> (defun my-car (x) (car x))
>
> (my-car '(42)) -> 42
>
> (let ((x (list 42))) (setf (my-car x) 3)) -> error
>
> And now the fun bit:
>
> (defun (setf my-car) (new-car cell)
> (setf (car cell) new-car))

Here is how (setf car) may be implemented (not by the user, but by the
implementors):

(defun (setf car) (new-car cell)
(rplaca cell new-car)
new-car)


> (let ((x (list 42))) (setf (my-car x) 3)) -> 3

That's why:

(let ((x (list 42))) (setf (car x) 3)) -> 3

works.

Alden L. Pierre

unread,
Oct 20, 2006, 12:02:58 PM10/20/06
to
Pascal Bourguignon wrote:
> "Alden L. Pierre" <alden....@gmail.com> writes:
>> When I see (setf (car x) 'n) here is how it breaks down in my mind:
>>
>> 1. 'n gets evaluated and returns N.
>> 2. (car x) gets evaluated and returns the first element in the set x.
>> 3. Now we are going to combine steps 1 and 2.
>> 4.( setf steps1 steps2 )
>
> You should send us a postcard from your fantasy world.
> It sounds interesting!
>

You are free to not respond to any of my questions. As I mentioned
earlier when writing this thread, I'm learning clisp.

Regards,
Alden

Pascal Bourguignon

unread,
Oct 20, 2006, 12:21:29 PM10/20/06
to

Then read more tutorials and references before trying to theorize.

If you'd read the chapter 3 of CLHS, you'd learn easily that the way
(setf (car x) 'n) is interpreted is:

(setf (car x) 'n) is a list, so we look the first item.

setf doesn't denote a special operator.

setf denotes a macro, therefore we call the setf macro function with
as arguments (setf (car x) 'n) and the current environment. Then we
evaluate the resulting form.


Since we don't know the source of setf and we don't care, we'll just
ask an implementation what it macroexpands this setf form to:

(macroexpand '(setf (car x) 'n)) --> (SYSTEM::%RPLACA X 'N) ;

So now we evaluate (SYSTEM::%RPLACA X 'N).

It's a list, so we look the first item.
SYSTEM::%RPLACA is not a special operator.
SYSTEM::%RPLACA is not a macro.
So it must be a function. Therefore we will call this function, but first
we must evaluate the arguments.

Let's evaluate X.

X is a symbol.
X doesn't denote a symbol-macro,
so X must denote a variable and we return the value of this variable: (A B C)

(quote n) is a list
so we look the first item: quote.

quote is a special operator. The special rule for the special
operator quote is to return the second element of the form. So we return N.

Finally, we can call the function denoted by SYSTEM::%RPLACA with the
arguments (A B C) and N, and return the result.


Now, this function is an implementation specific implementation of
CL:RPLACA. Reade clhs about RPLACA to know what will happen and what
result we will get.


--
__Pascal Bourguignon__ http://www.informatimago.com/

Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.

Rob Thorpe

unread,
Oct 20, 2006, 12:58:10 PM10/20/06
to

It confused me when I first saw it too, and I already knew other lisps,
just not Common Lisp.

The way setf behaves though is similar to how other forms behave,
things like defun, where some of the forms the programmer enters are
not evaluated, but instead have special meanings. The difference with
setf is that the special meaning is made to precisely reflect the
normal meaning but in assignment.

Sometimes people call expressions which can be assigned to "setf-able"
which seems a fair way of describing them.

Ken Tilton

unread,
Oct 20, 2006, 12:57:43 PM10/20/06
to

Alden L. Pierre wrote:
> Pascal Bourguignon wrote:
>
>> "Alden L. Pierre" <alden....@gmail.com> writes:
>>
>>> When I see (setf (car x) 'n) here is how it breaks down in my mind:
>>>
>>> 1. 'n gets evaluated and returns N.
>>> 2. (car x) gets evaluated and returns the first element in the set x.

btw, this is what I have been trying to say. No, what happens here
(loosely speaking) is that Lisp goes looking for (setf car), which is a
completely different function than (car x) the reader function.

>>> 3. Now we are going to combine steps 1 and 2.
>>> 4.( setf steps1 steps2 )
>>
>>
>> You should send us a postcard from your fantasy world. It sounds
>> interesting!
>>
>
> You are free to not respond to any of my questions. As I mentioned
> earlier when writing this thread, I'm learning clisp.

You are learning Common Lisp or CL. clisp is a tempting abbreviation,
but happens to be the name of one implementation.

I went thru the same thing when I looked at Dylan on my RtL, and recall
distinctly two WTF? questions to the Dylan team: how the hell I could
assign to a function call, and what the hell was the editor doing when I
pressed TAB. :)

Thomas A. Russ

unread,
Oct 20, 2006, 12:52:53 PM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> When I see (setf (car x) 'n) here is how it breaks down in my mind:
>
> 1. 'n gets evaluated and returns N.
> 2. (car x) gets evaluated and returns the first element in the set x.

This would be true if SETF were a function. But since it is a macro, it
does not have to evaluate its arguments. In the case of SETF, it needs
to get a generalized PLACE as the first argument. This is not evaluated
in the conventional lisp sense, but is instead taken as a description of
where the modification will take place.

> 3. Now we are going to combine steps 1 and 2.
> 4.( setf steps1 steps2 )
>
> Naturally setf needs a place and value. In this case the place is x and
> the value is n.

Not quite. The place is (car x), in other words the first element of
the CONS that is contained in X. As someone else pointed out, there is
a specific older function RPLACA that directly does this.

By the way, the other list accessor functions such as SECOND, THIRD,
etc. can also serve as places for SETF. Note that this is not true of
all functions in general. Only those that SETF knows about, either
because they are built-in to the implementation or because the
programmer has told SETF about them by defining SETF methods or using
the DEFSETF form.

It is important to understand the Lisp evaluation model, but it isn't
totally uniform, because some macros and special forms do not evaluate
their arguments. This is really crucial for certain forms like IF,
which would not really be useful if it evaluated all of its arguments.
Other times, the lack of evaluation is really just a convenience (like
the DEFUN macro) so that you don't need to put quotes everywhere. SETF
is sort of like that as well.

> I think I've got it. Please correct me if I'm wrong. When setf begins to
> do it's evaluation here are the things that will take place, again this
> is how I process the information:
>
> 1. take the value, in this case 'n

Yes.

> 2. now because (car x) returns the first element of our set, switch that
> with 'n.

No. (car x) does not get evaluated. It describes a place.

> 3. 'n is now in the set x, because setf needs a place to assign a value
> by definition. When (car x) gets evaluated we are referring to
> "place" as the first element of the set x.

Not quite. N is in the list pointed to by X because we have modified
the actual list datastructure by replacing the first element in that
datastructure. To see that it is really the underlying datastructure
that gets modified, consider the following example and see if you
understand what is happening:

(setf x (list 'a 'b 'c))

(serf y x)
x ; ==> (A B C)
y ; ==> (A B C)
(setf (second x) 'n)

What do you expect if you look at X and Y?


--
Thomas A. Russ, USC/Information Sciences Institute

Alden L. Pierre

unread,
Oct 20, 2006, 1:08:37 PM10/20/06
to
Pascal Bourguignon wrote:
> Then read more tutorials and references before trying to theorize.
I'm trying to make a theory? I mentioned this is the way I process the
information and then went on to explain the steps I'm using to process
the expression I see before me.

>
> If you'd read the chapter 3 of CLHS, you'd learn easily that the way
> (setf (car x) 'n) is interpreted is:
>
I'm using Paul Graham Ansi Common Lisp book which I purchased. The book
received great reviews and thus far presented the material in a well
thought out manner. He presented another method in using setf which
confused me, rather then move forward to the next section, I sort to
find some clarity on what makes the function operates the way it does.

Thank you for mentioning CLHS, I will also use this book along with Paul
Graham book.

It would have been great if you replied in this manner from the
beginning. Your knowledge is greatly appreciated, but the snide remarks
is unwelecomed :-).

Had I known about CLHS before hand, I might have been able to save some
money.

Regards,
Alden

Alden L. Pierre

unread,
Oct 20, 2006, 1:17:29 PM10/20/06
to
Ken Tilton wrote:
> You are learning Common Lisp or CL. clisp is a tempting abbreviation,

http://www.paulgraham.com/acl.html if you follow this link, it will
bring you to the book I'm using. It says Ansi Common Lisp, so going by
the title I believe I'm learning common lisp. I presume clisp denotes
common lisp.

> I went thru the same thing when I looked at Dylan on my RtL, and recall
> distinctly two WTF? questions to the Dylan team: how the hell I could
> assign to a function call, and what the hell was the editor doing when I
> pressed TAB. :)

It's always good to know I'm not the first nor the last (I hope) who has
gone through this ordeal :-).

Regards,
Alden

Zach Beane

unread,
Oct 20, 2006, 1:38:22 PM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> Ken Tilton wrote:
> > You are learning Common Lisp or CL. clisp is a tempting
> > abbreviation,
>
> http://www.paulgraham.com/acl.html if you follow this link, it will
> bring you to the book I'm using. It says Ansi Common Lisp, so going by
> the title I believe I'm learning common lisp. I presume clisp denotes
> common lisp.

That's incorrect. "clisp" denotes a particular implementation of
Common Lisp, GNU CLISP. If you want to write something short to refer
to Common Lisp, use "CL" or just "Lisp". In comp.lang.lisp, neither of
those are ambiguous.

Zach

Ken Tilton

unread,
Oct 20, 2006, 1:41:18 PM10/20/06
to

Alden L. Pierre wrote:
> Ken Tilton wrote:
>
>> You are learning Common Lisp or CL. clisp is a tempting abbreviation,
>
>
> http://www.paulgraham.com/acl.html if you follow this link, it will
> bring you to the book I'm using. It says Ansi Common Lisp, so going by
> the title I believe I'm learning common lisp.

So far so good.

> I presume clisp denotes
> common lisp.

Now you are just being dense.

hth, kt

Alden L. Pierre

unread,
Oct 20, 2006, 1:50:57 PM10/20/06
to
Very well, I'll use the proper notation(CL or Lisp) next time :-) .

Regards,
Alden

Pascal Costanza

unread,
Oct 20, 2006, 1:55:19 PM10/20/06
to

A good way to understand setf is to compare it to assignment operators
in other languages. For example, consider the following statement.

x = 1;

This will assign 1 to the variable x.

In almost all languages, the left-hand side of an assignment can be more
complex than a variable. For example it can be an array access:

x[0] = 1;


This will assign 1 to the component 0 in the array x.

x.name = "Dilbert";

This assumes that x is some kind of object with a field name, and this
will assign the string "Dilbert" to it.

x.table[0] = 1;

This assumes that x is some kind of object with a field table that in
turn is an array, and this will assign 1 to the component 0 of that array.

And so on.

Common Lisp's setf is exactly like such a generic assignment operator.
Here are some examples:

; this assigns 1 to x
(setf x 1)

; this assigns 1 to the component 0 of the array x
(setf (aref x 0) 1)

; this assigns "Dilbert" to the field name in object x
(setf (name x) "Dilbert")

; this assigns 1 to the component 0 in the field table in object x
(setf (aref (table x) 0) 1)

; this assigns 1 to the field car of the object x
(setf (car x) 1)


When I have said "object" here, I didn't necessarily mean it in the
object-oriented sense. But indeed, a cons cell can be understood as an
object with exactly two fields 'car and 'cdr.

The neat thing about Common Lisp here is that you can provide your own
left-hand side constructs for 'setf, something that you typically cannot
do for assignment operators in other languages (or only in very limited
ways).


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/

Alden L. Pierre

unread,
Oct 20, 2006, 2:39:53 PM10/20/06
to
Your example has brought clarity with the setf assignment operator. This
will definitely be added to my notes.

Regards,
Alden

Thomas Lindgren

unread,
Oct 20, 2006, 3:03:37 PM10/20/06
to

"Alden L. Pierre" <alden....@gmail.com> writes:

> Had I known about CLHS before hand, I might have been able to save
> some money.

Well, the CLHS really is a specification, not a tutorial. So it might
be a bit terse for the beginner. Or non-expert, even.

Here are some gratis resources:
http://www.paulgraham.com/onlisptext.html
http://www.gigamonkeys.com/book/
and of course,
http://www.lisp.org/HyperSpec/FrontMatter/index.html

Best,
Thomas
--
Thomas Lindgren

"Ever tried. Ever failed. No matter. Try again. Fail again. Fail better."

Pascal Bourguignon

unread,
Oct 20, 2006, 3:10:01 PM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> Pascal Bourguignon wrote:
>> Then read more tutorials and references before trying to theorize.
> I'm trying to make a theory? I mentioned this is the way I process the
> information and then went on to explain the steps I'm using to process
> the expression I see before me.
>> If you'd read the chapter 3 of CLHS, you'd learn easily that the way
>> (setf (car x) 'n) is interpreted is:
>>
> I'm using Paul Graham Ansi Common Lisp book which I purchased. The
> book received great reviews and thus far presented the material in a
> well thought out manner. He presented another method in using setf
> which
> confused me, rather then move forward to the next section, I sort to
> find some clarity on what makes the function operates the way it does.

The key is that setf is not a function, but a macro, and therefore the
evaluation rules for the functions don't apply: the arguments are not
evaluated before the macro is called. In (setf (car x) 'n), the form
(car x) is not evaluated, the function car is not called. Only X and
(QUOTE N) are evaluated, before calling RPLACA.

> Thank you for mentioning CLHS, I will also use this book along with Paul
> Graham book.

> [...]


> It would have been great if you replied in this manner from the
> beginning. Your knowledge is greatly appreciated, but the snide
> remarks is unwelecomed :-).

Sorry, I thought everybody knew about CLHS.


> Had I known about CLHS before hand, I might have been able to save
> some money.

It's hard to believe. For more than ten years already there's this
thing named the world wide web, and these tools named search engines
(google, yahoo, altavista, etc), so it's really easy to find tutorials
and other reference documents about any subject.


And most of the lisp tutorials mention soon enough the differences
between the various kind of forms, and how they're evaluated.

For example, http://www.notam02.no/internt/cm-sys/cm-2.2/doc/clt.html
mentions Special Forms as its 8th ToC item and SETF as its 14th.


But it's true that there is perhaps too much material. Google returns
more than 4 million hits for lisp tutorial. And not all of them
start with a formal description of the evaluation rules. (I suppose
that's what the references like CLHS are for).


http://www.cliki.net/
http://www.apl.jhu.edu/~hall/lisp.html#Section1
http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm

--
__Pascal Bourguignon__ http://www.informatimago.com/

"Do not adjust your mind, there is a fault in reality"
-- on a wall many years ago in Oxford.

Edgar

unread,
Oct 20, 2006, 3:23:28 PM10/20/06
to
Pascal Costanza wrote:
>
> The neat thing about Common Lisp here is that you can provide your own
> left-hand side constructs for 'setf, something that you typically cannot
> do for assignment operators in other languages (or only in very limited
> ways).
>

Hmmm,

Defining a new setf function is kinda like overloading the '=' operator
in C++ (except setf is more general). So in lisp we can 'overload' the
setf 'assignment operator', but not any other operator like '*' (though
it can be shadowed). This seems to be an inconsistency.

Edgar.

Pascal Bourguignon

unread,
Oct 20, 2006, 3:37:02 PM10/20/06
to
"Edgar" <edgar...@comcast.net> writes:

> Pascal Costanza wrote:
>>
>> The neat thing about Common Lisp here is that you can provide your own
>> left-hand side constructs for 'setf, something that you typically cannot
>> do for assignment operators in other languages (or only in very limited
>> ways).
>>
>
> Hmmm,
>
> Defining a new setf function is kinda like overloading the '=' operator
> in C++ (except setf is more general).


Not exactly.


(setf (slot-value x 'name) "Bill") x->name = "Bill";

(setf (aref x 0) 42) x[0] = 42;

(setf (car (aref x (incf i))) 'hi) x[++i]->car = "hi";

The = operator is not modified. What's added is the syntax to access
some field/slot.


For example, you can define an accessor for the slot named NAME:

(defmethod name ((x <class>)) (slot-value x 'name))
(defmethod (setf name) (value (x <class>)) (setf (slot-value x 'name) value))

(setf (name x) "Bill") x->name = "Bill";

In C, you could do: #define NAME(x) ((x)->name)
NAME(x) = "Bill";

but things become more complex in C for things like:

(setf (cnt (car (aref x (incf i)))) (incf i)) x[++i]->car.cnt = ++i;
/* (wrong) */

> So in lisp we can 'overload' the
> setf 'assignment operator', but not any other operator like '*' (though
> it can be shadowed). This seems to be an inconsistency.

--
__Pascal Bourguignon__ http://www.informatimago.com/

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.

Matthias Buelow

unread,
Oct 20, 2006, 3:59:47 PM10/20/06
to
Edgar <edgar...@comcast.net> wrote:

> Defining a new setf function is kinda like overloading the '=' operator
> in C++ (except setf is more general). So in lisp we can 'overload' the
> setf 'assignment operator', but not any other operator like '*' (though
> it can be shadowed). This seems to be an inconsistency.

How about something like the following (there might be better ways to
do it):

(defstruct my-weird-matrix-type
...)

(defun my-weird-matrix-multiplication (x &rest foo)
...)

(let ((old-* #'*))
(defmacro * (&rest stuff)
`(if (and ,stuff
(typep (car ,stuff) 'my-weird-matrix-type))
(my-weird-matrix-multiplication ,@stuff)
(funcall ,old-* ,@stuff)))


Pascal Bourguignon

unread,
Oct 20, 2006, 5:55:07 PM10/20/06
to
Matthias Buelow <m...@incubus.de> writes:

> Edgar <edgar...@comcast.net> wrote:
>
>> Defining a new setf function is kinda like overloading the '=' operator
>> in C++ (except setf is more general). So in lisp we can 'overload' the
>> setf 'assignment operator', but not any other operator like '*' (though
>> it can be shadowed). This seems to be an inconsistency.
>
> How about something like the following (there might be better ways to
> do it):
>
> (defstruct my-weird-matrix-type
> ...)
>
> (defun my-weird-matrix-multiplication (x &rest foo)
> ...)
>
> (let ((old-* #'*))
> (defmacro * (&rest stuff)

This is forbidden by CL.
You could macrolet a symbol in CL that is bound to a function or macro,
but you cannot redefine like this.

> `(if (and ,stuff
> (typep (car ,stuff) 'my-weird-matrix-type))
> (my-weird-matrix-multiplication ,@stuff)
> (funcall ,old-* ,@stuff)))

It's best to leave symbols in CL alone, and use your own symbol.

Moreove, * is a function, there's no reason to make it a macro.


(shadow '*)
(defun * (&rest args)
(if (find 'my-weird-matrix-type args :key (function type-of))
(apply (function my-weird-matrix-multiplication) args)
(apply (function cl:*) args)))

If you don't like the rules of section 11.1.2.1.2, one thing that you
can do is to define your own MY-CL package, from where you export your
own symbols corresponding to those of CL.

(setf (symbol-function 'my-cl:+) (symbol-function 'cl:+))
;; etc

This mostly work. Some things are harder to get well, like the
variables and constants, [ you'll have (not (eq 'my-cl:nil my-cl:nil)) ],
but you'll be able to redefine freely any symbol in my-cl.


--
__Pascal Bourguignon__ http://www.informatimago.com/

You never feed me.
Perhaps I'll sleep on your face.
That will sure show you.

Bill Atkins

unread,
Oct 20, 2006, 6:38:04 PM10/20/06
to
"Alden L. Pierre" <alden....@gmail.com> writes:

> Hello,
>
> I'm in the process of teaching myself clisp. I'm using Paul Graham


> Ansi Common Lisp book. While reading this book I've stumble upon
> sections, which I currently don't understand fully.
>
> setf:
>
> 1. It's been mentioned to avoid using setf and things like it.
>
> I understand this expression (setf x (list 'a 'b 'c))
> x is a set which contains ABC.
>
> How ever I don't understand this expression fully:
> (setf (car x) 'n) how is it that x contains NBC? I know the car
> function will return a complete list minus the first element. Also N
> is to be placed in a new a variable, in this case it's the list, how
> is it that x now contains NBC? I'm trying to understand how the
> expression gets evaluated and why did the x variable get modified?
>

> Regards
> Alden

Are you familiar with Practical Common Lisp (available online at
http://www.gigamonkeys.com/book or from Amazon)? ANSI Common Lisp
isn't, at least IMHO, a tremendously helpful book for beginners. Try
starting with PCL and then going back through ANSI Common Lisp once
you've got a firmer grasp of the language.

Some other points:

1. The language is not "clisp"; I'm sure this was pointed out
somewhere else in the thread.

2. X will never contain NBC or anything like it. NBC is a symbol; X is
a list of three symbols. So

x
;; => (A B C)
(setf (car x) 'n)
;; => (N B C)

The list '(N B C) has nothing to do with the symbol NBC.

3. N is not "to be placed in a new variable." There is one variable
X. The first element of X is set to the symbol N. That's all.

Pascal Costanza

unread,
Oct 20, 2006, 7:01:04 PM10/20/06
to

The other Pascal's comment is correct, but let me add that just because
setf is somewhat similar to operator overloading in C++ doesn't mean
that operator overloading would be a good idea for Lisp, or that it even
makes sense to talk about operator overloading in Lisp.

Common Lisp's setf is a macro, so must base its decision on statically
available information. This works quite well in the case of setf because
the macroexpansion of a setf form can indeed be based solely on the
static form of the first argument. Common Lisp offers other
user-extensible macros based on statically available information, like
for example the very generic compiler macros. It's also relatively
straightforward to build your own such extensible macros.

In the case of * and similar operations, you cannot get at the
information that would be necessary to base your "expansion" on, namely
the types of the arguments. Since Common Lisp is a dynamically typed
language, the types will only be known at run time in the general case.
The preferred way to make functions depend on dynamic type information
is via CLOS-style generic functions. Operations like * are indeed
generic in the sense that they work for several types, but they are not
user-extensible.

The only way to make the behavior of such operations depend on static
information is by choosing different names. For example, if you want
matrix multiplication, just define your own function 'matrix-*, or so,
or your own '* in your own package. It's probably a good idea to try to
understand that this is indeed as good as static operator overloading.

sanky...@gmail.com

unread,
Oct 21, 2006, 12:38:57 PM10/21/06
to
If setf is a macro, why do I get this in LispWorks:

> #'setf
#<function SETF 201557E2>

sanket.

On Oct 20, 4:01 pm, Pascal Costanza <p...@p-cos.net> wrote:
> Edgar wrote:
> > Pascal Costanza wrote:
> >> The neat thing about Common Lisp here is that you can provide your own
> >> left-hand side constructs for 'setf, something that you typically cannot
> >> do for assignment operators in other languages (or only in very limited
> >> ways).
>
> > Hmmm,
>
> > Defining a new setf function is kinda like overloading the '=' operator
> > in C++ (except setf is more general). So in lisp we can 'overload' the
> > setf 'assignment operator', but not any other operator like '*' (though

> > it can be shadowed). This seems to be an inconsistency.The other Pascal's comment is correct, but let me add that just because

Raffael Cavallaro

unread,
Oct 21, 2006, 12:47:18 PM10/21/06
to
On 2006-10-21 12:38:57 -0400, sanky...@gmail.com said:

> If setf is a macro, why do I get this in LispWorks:
>
>> #'setf
> #<function SETF 201557E2>

I get this:

CL-USER 9 > #'setf

Error: SETF names a macro -- bad arg for FUNCTION.
1 (abort) Return to level 0.
2 Return to top loop level 0.

Jack Unrue

unread,
Oct 21, 2006, 1:08:51 PM10/21/06
to

CLISP 2.41:

[1]> #'setf

*** - FUNCTION: undefined function SETF


ECL 0.9i:

> #'setf
The function SETF is undefined.


SBCL 0.9.17:

* #'setf

#<CLOSURE (LAMBDA (&REST SB-C::ARGS)) {99911A5}>


Corman 3.0 beta 2:

?#'setf
#< COMPILED-FUNCTION: #x100E7F38 >


--
Jack Unrue

Bill Atkins

unread,
Oct 21, 2006, 1:35:41 PM10/21/06
to
Raffael Cavallaro <raffaelcavallaro@pas-d'espam-s'il-vous-plait-mac.com> writes:

> I get this:
>
> CL-USER 9 > #'setf
>
> Error: SETF names a macro -- bad arg for FUNCTION.
> 1 (abort) Return to level 0.
> 2 Return to top loop level 0.

Me too.

sanky...@gmail.com

unread,
Oct 21, 2006, 2:39:06 PM10/21/06
to
Seems like Jack Unrue got <function> for Corman Lisp. And my LispWorks
keeps calling it <function>. it also disassembles setf for me.

I would like to believe setf is a macro. any experts have any insight
on this?

sanket.

On Oct 21, 10:08 am, Jack Unrue <no.s...@example.tld> wrote:
> On Sat, 21 Oct 2006 12:47:18 -0400, Raffael Cavallaro <raffaelcavallaro@pas-d'espam-s'il-vous-plait-mac.com> wrote:
> > On 2006-10-21 12:38:57 -0400, sankymo...@gmail.com said:
>
> > > If setf is a macro, why do I get this in LispWorks:
>
> > >> #'setf
> > > #<function SETF 201557E2>
>
> > I get this:
>
> > CL-USER 9 > #'setf
>
> > Error: SETF names a macro -- bad arg for FUNCTION.
> > 1 (abort) Return to level 0.

> > 2 Return to top loop level 0.CLISP 2.41:


>
> [1]> #'setf
>
> *** - FUNCTION: undefined function SETF
>
> ECL 0.9i:
>

> > #'setfThe function SETF is undefined.

Pascal Bourguignon

unread,
Oct 21, 2006, 2:56:27 PM10/21/06
to
sanky...@gmail.com writes:

> If setf is a macro, why do I get this in LispWorks:
>
>> #'setf
> #<function SETF 201557E2>

Where do you think the macro function is stored?

Remember, macros are just like normal functions!

Only all the macro functions have the same signature (take a form and
an environment, and return a form), and are called (usually) by the
compiler.


If you read more about CL, you might encounter the function
MACRO-FUNCTION, which is the correct way to know if a symbol is FBOUND
to a macro.


LISP> (fboundp 'setf)
T

LISP> (symbol-function 'setf)
#<MACRO #<COMPILED-FUNCTION SETF>>

LISP> (macro-function (quote setf))
#<COMPILED-FUNCTION SETF>

LISP> (macro-function 'sin) ; for a non-macro function, it returns:
NIL

LISP> (function setf)

*** - FUNCTION: undefined function SETF

--
__Pascal Bourguignon__ http://www.informatimago.com/

"This statement is false." In Lisp: (defun Q () (eq nil (Q)))

Bill Atkins

unread,
Oct 21, 2006, 4:08:10 PM10/21/06
to
sanky...@gmail.com writes:

> Seems like Jack Unrue got <function> for Corman Lisp. And my LispWorks
> keeps calling it <function>. it also disassembles setf for me.
>
> I would like to believe setf is a macro. any experts have any insight
> on this?

No need to "believe" it. It's part of the specification. As Pascal
recommended, try (macro-function 'setf) to convince yourself. Then
try (macro-function 'cos) to see the difference.

What LispWorks are you running?

Pascal Costanza

unread,
Oct 21, 2006, 7:05:06 PM10/21/06
to
sanky...@gmail.com wrote:
> If setf is a macro, why do I get this in LispWorks:
>
>> #'setf
> #<function SETF 201557E2>

The HyperSpec is your friend. See the section on the special operator
function. There it is stated that "it is an error to use function on a
symbol that denotes a macro or special form. An implementation may
choose not to signal this error for performance reasons, but
implementations are forbidden from defining the failure to signal an
error as a useful behavior."

You can only be sure that a symbol names a function when fboundp returns
true but both macro-function and special-operator-p return false.

Carl Taylor

unread,
Oct 21, 2006, 8:12:58 PM10/21/06
to

Using the Personal Edition of LW 4.4.6 one gets the following results.

Carl Taylor

CL-USER 9 > (macro-function 'setf)
#<function SETF 201557E2>

CL-USER 10 > (fboundp 'setf)
#<function SETF 201557E2>

CL-USER 11 > (macro-function (quote setf))
#<function SETF 201557E2>

CL-USER 12 > (function setf)
#<function SETF 201557E2>

CL-USER 13 > (describe 'setf)

SETF is a SYMBOL
NAME "SETF"
VALUE #<unbound value>
FUNCTION #<function SETF 201557E2>
PLIST (PKG::SYMBOL-NAME-STRING "SETF" SYSTEM::FUNCTION-DSPEC T)
PACKAGE #<PACKAGE COMMON-LISP>

CL-USER 14 > (describe #'setf)

#<function SETF 201557E2> is a LOW:COMPILED-FUNCTION-OBJECT
CODE #<code SETF (318) 201557E2>
CONSTANTS (#<record SETF 769 #<record &REST SETF::ARGS &ENVIRONMENT
SETF::ENV> #<record (&ENVIRONMENT . 4194821) (DSPEC::%%MACROARG%% .
4194310)>> T #<function SEQ::CDR-1ARG 209C5A8A> (&REST SETF::ARGS)
:MACRO DSPEC::CHECK-LAMBDA-LIST-TOP-LEVEL #<function SEQ::CDDR-1ARG
209C588A> #<function SEQ::CAR-1ARG 209C5B32> #<function SEQ::CADR-1ARG
209C595A> SETF::SETF-FORM ...)

Pascal Bourguignon

unread,
Oct 21, 2006, 8:29:25 PM10/21/06
to
"Carl Taylor" <carlt...@att.net> writes:
> [...]

> CL-USER 13 > (describe 'setf)
>
> SETF is a SYMBOL
> NAME "SETF"
> VALUE #<unbound value>
> FUNCTION #<function SETF 201557E2>
> PLIST (PKG::SYMBOL-NAME-STRING "SETF" SYSTEM::FUNCTION-DSPEC T)
> PACKAGE #<PACKAGE COMMON-LISP>
>
> CL-USER 14 > (describe #'setf)
>
> #<function SETF 201557E2> is a LOW:COMPILED-FUNCTION-OBJECT
> CODE #<code SETF (318) 201557E2>
> CONSTANTS (#<record SETF 769 #<record &REST SETF::ARGS
> &ENVIRONMENT SETF::ENV> #<record (&ENVIRONMENT . 4194821)
> (DSPEC::%%MACROARG%% . 4194310)>> T #<function SEQ::CDR-1ARG 209C5A8A>
> (&REST SETF::ARGS) :MACRO DSPEC::CHECK-LAMBDA-LIST-TOP-LEVEL
> #<function SEQ::CDDR-1ARG 209C588A> #<function SEQ::CAR-1ARG 209C5B32>
> #<function SEQ::CADR-1ARG 209C595A> SETF::SETF-FORM ...)

There's a little of a circular dependency:

- you cannot understand everything in CLHS unless you know how some
implementation(s) work.

- you cannot understand (interpret) correctly the results of an
implementation if you don't know CLHS.

In your implementation DESCRIBE applied on a symbol gives the five
"slots" of that symbol. Something stored in the function slot doesn't
means that there is a _function_ named by this symbol.

--
__Pascal Bourguignon__ http://www.informatimago.com/

Small brave carnivores
Kill pine cones and mosquitoes
Fear vacuum cleaner

sanky...@gmail.com

unread,
Oct 21, 2006, 9:44:51 PM10/21/06
to
you guys are awesome! asked one question and learned about so many
useful functions:

fboundp
symbol-function
macro-function
special-operator-p
describe
function

thanks!

sanket.

On Oct 21, 5:29 pm, Pascal Bourguignon <p...@informatimago.com> wrote:


> "Carl Taylor" <carltay...@att.net> writes:
> > [...]
> > CL-USER 13 > (describe 'setf)
>
> > SETF is a SYMBOL
> > NAME "SETF"
> > VALUE #<unbound value>
> > FUNCTION #<function SETF 201557E2>
> > PLIST (PKG::SYMBOL-NAME-STRING "SETF" SYSTEM::FUNCTION-DSPEC T)
> > PACKAGE #<PACKAGE COMMON-LISP>
>
> > CL-USER 14 > (describe #'setf)
>
> > #<function SETF 201557E2> is a LOW:COMPILED-FUNCTION-OBJECT
> > CODE #<code SETF (318) 201557E2>
> > CONSTANTS (#<record SETF 769 #<record &REST SETF::ARGS
> > &ENVIRONMENT SETF::ENV> #<record (&ENVIRONMENT . 4194821)
> > (DSPEC::%%MACROARG%% . 4194310)>> T #<function SEQ::CDR-1ARG 209C5A8A>
> > (&REST SETF::ARGS) :MACRO DSPEC::CHECK-LAMBDA-LIST-TOP-LEVEL
> > #<function SEQ::CDDR-1ARG 209C588A> #<function SEQ::CAR-1ARG 209C5B32>

> > #<function SEQ::CADR-1ARG 209C595A> SETF::SETF-FORM ...)There's a little of a circular dependency:

André Thieme

unread,
Nov 6, 2006, 11:44:39 AM11/6/06
to
Alden L. Pierre schrieb:
> Peder O. Klingenberg wrote:
>> You are thinking of CDR.
>>
> Yes, your right. So much information for such a small book.

>
>>> Also N is to be placed in a new a variable, in this case it's the
>>> list, how is it that x now contains NBC?
>>
>> N is to be placed in the place named by the first argument to the
>> SETF, that is, the first element of X.

>>
>>> I'm trying to understand how the expression gets evaluated and why
>>> did the x variable get modified?
>>
>> What did you expect to happen?
>
> When I see (setf (car x) 'n) here is how it breaks down in my mind:
>
> 1. 'n gets evaluated and returns N.
> 2. (car x) gets evaluated and returns the first element in the set x.
> 3. Now we are going to combine steps 1 and 2.
> 4.( setf steps1 steps2 )

I know, 1000 others already have answered it, but here is my idea.
Perhaps do you know the language C? Let's take a C array x with 10
elements.
When you say printf("Value: %d", x[4]); you will print out the int
that is stored at index 4 of the array x. Let's say x[4] == 5.

The [] operator changes it meanings in C as it does in Lisp, depending
on the position where you use it. If you say:
x[4] = 17;

then you would think that the array cell with index 4 is now updated
to the value 17. But when you see basically the same thing in Lisp
you understand it this way:
x[4] has the value 5. So
x[4] = 17; means the same thing as if you said: 5 = 17;

Like in C the operator [] has a different meaning when it is on the
left side of a = the same happens with CAR in Lisp too when it appears
in a setf.
(defvar x (make-array 10))

We want to do:
x[4] = 17;
First thing we do is to replace the = with setf:

x[4] setf 17;

Now we put parens around the expression and remove the semicolon:
(x[4] setf 17)

Now setf walks to position 1 in the list:
(setf x[4] 17)

Instead of [] we use Lisps AREF:
(setf (aref x 4) 17)

Instead of an array you used a list and instead of AREF you used CAR.


André
--

André Thieme

unread,
Nov 6, 2006, 11:52:47 AM11/6/06
to
Alden L. Pierre schrieb:

> Had I known about CLHS before hand, I might have been able to save some
> money.

Don't worry, you did not waste any money. The book you bought is very
good for learning lisp. The CLHS is a specification that works very well
as a reference, but not for learning.


André
--

0 new messages