From: Jim Newton
Subject: magic of setf
Date: 
Message-ID: <2k65i5F17iv5kU1@uni-berlin.de>
hi.  i've been using a dialect of list for several years before
being introduced to common lisp.  this dialect had no setf, but
rather used set and setq, so the magic of setf seems a bit overwhelming
to me.  I'm not sure i really understand what it does.  It acts sort
of like a symbolic algebra inversion mechanism.  but it does not
always seem to work as i'd expect.

for example i can say

(setq x (acos 1))

but i cannot say

(setf (cos x) 1)
*** - EVAL: the function (SETF COS) is undefined

Can someone explain to me what setf really does?

-jim

From: Ari Johnson
Subject: Re: magic of setf
Date: 
Message-ID: <EklDc.101$nc.40@fed1read03>
Jim Newton wrote:
> hi.  i've been using a dialect of list for several years before
> being introduced to common lisp.  this dialect had no setf, but
> rather used set and setq, so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.  but it does not
> always seem to work as i'd expect.
> 
> for example i can say
> 
> (setq x (acos 1))
> 
> but i cannot say
> 
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined
> 
> Can someone explain to me what setf really does?

The intuitive definition is that setf changes the value stored in a 
certain place.  That place might be a symbol, a property of a symbol, or 
something more complex.  For example:

(setq a '(1 2 3)) ; store (1 2 3) in A
(setf (car a) 0) ; A is now (0 2 3)
(setf (cdr a) '(4 5)) ; A is now (0 4 5)

What setf actually /does/ is more complicated, but essentially you can 
think of it as a macro that knows how to store a value in any place. 
For example, in CLISP I get:
[1]> (macroexpand-1 '(setf (car a) 0))
(SYSTEM::%RPLACA A 0) ;
T
From: Paul F. Dietz
Subject: Re: magic of setf
Date: 
Message-ID: <DtCdnV4Ga7R2fEDdRVn-sQ@dls.net>
Jim Newton wrote:

> hi.  i've been using a dialect of list for several years before
> being introduced to common lisp.  this dialect had no setf, but
> rather used set and setq, so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.  but it does not
> always seem to work as i'd expect.
> 
> for example i can say
> 
> (setq x (acos 1))
> 
> but i cannot say
> 
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined
> 
> Can someone explain to me what setf really does?


SETF is a macro.  Basically, it looks to see if it
'knows' how to assign to the first argument, and expands
into the appropriate code.  If it does, it calls a setf
function with name (setf <car of first argument>).  In
this case, COS has no setf expansion, so it turns into
that function call.

The standardized operators for which SETF works are called
'acccessors' in the CL standard.  CAR is an accessor, for
example, but COS is not (it's just a function.)

See section 5.1 of CLtS, and the page for SETF.  Also
try looking at the result of this:

   (macroexpand '(setf (car x) y))

and the same on other setf forms.

	Paul
From: Paul F. Dietz
Subject: Re: magic of setf
Date: 
Message-ID: <DtCdnVkGa7Tzf0DdRVn-sQ@dls.net>
I wrote:

> 'knows' how to assign to the first argument, and expands
> into the appropriate code.  If it does, it calls a setf

Er, if it does *not*...

	Paul
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2k66gtF188lujU1@uni-berlin.de>
but i see that i can increase the data base of what setf
knows how to do.

(defun (setf x) ( y z)
   ...)

can i use this to make setf work with cos and acos?

-jim



Paul F. Dietz wrote:
> I wrote:
> 
>> 'knows' how to assign to the first argument, and expands
>> into the appropriate code.  If it does, it calls a setf
> 
> 
> Er, if it does *not*...
> 
>     Paul
From: Paul F. Dietz
Subject: Re: magic of setf
Date: 
Message-ID: <kNKdnRdZXMrBeEDdRVn-gw@dls.net>
Jim Newton wrote:
> but i see that i can increase the data base of what setf
> knows how to do.
> 
> (defun (setf x) ( y z)
>   ...)
> 
> can i use this to make setf work with cos and acos?

That would not be conforming CL (see CLtS, section 11.1.2.1.2).

	Paul


	
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2k677jF17llruU1@uni-berlin.de>
can i get CLtS, section 11.1.2.1.2 on the web?


Paul F. Dietz wrote:
> Jim Newton wrote:
> 
>> but i see that i can increase the data base of what setf
>> knows how to do.
>>
>> (defun (setf x) ( y z)
>>   ...)
>>
>> can i use this to make setf work with cos and acos?
> 
> 
> That would not be conforming CL (see CLtS, section 11.1.2.1.2).
> 
>     Paul
> 
> 
>     
From: Paul F. Dietz
Subject: Re: magic of setf
Date: 
Message-ID: <vJGdnSfchbpac0DdRVn-sw@dls.net>
Jim Newton wrote:
> can i get CLtS, section 11.1.2.1.2 on the web?

Yep!

http://www.cliki.net/CLHS

	Paul
From: Thomas A. Russ
Subject: Re: magic of setf
Date: 
Message-ID: <ymibrj3r7rm.fsf@sevak.isi.edu>
Jim Newton <·····@rdrop.com> writes:

> 
> can i get CLtS, section 11.1.2.1.2 on the web?


 http://www.lispworks.com/reference/HyperSpec/



-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2k66r8F18gq3fU1@uni-berlin.de>
here is what happens when i try to set a setf method for cos.
what's happening here?

[1]> (defun (setf cos) ( x y) (setq x (acos y)))

** - Continuable Error
INTERN("(SETF COMMON-LISP:COS)"): #<PACKAGE COMMON-LISP> is locked
If you continue (by typing 'continue'): Ignore the lock and proceed
1. Break [2]>


Jim Newton wrote:
> but i see that i can increase the data base of what setf
> knows how to do.
> 
> (defun (setf x) ( y z)
>   ...)
> 
> can i use this to make setf work with cos and acos?
> 
> -jim
> 
> 
> 
> Paul F. Dietz wrote:
> 
>> I wrote:
>>
>>> 'knows' how to assign to the first argument, and expands
>>> into the appropriate code.  If it does, it calls a setf
>>
>>
>>
>> Er, if it does *not*...
>>
>>     Paul
> 
> 
From: Pascal Costanza
Subject: Re: magic of setf
Date: 
Message-ID: <cbl63c$b4d$1@newsreader2.netcologne.de>
Jim Newton wrote:

> here is what happens when i try to set a setf method for cos.
> what's happening here?
> 
> [1]> (defun (setf cos) ( x y) (setq x (acos y)))

There are several things going on here:

a) You are not allowed to define a setter on a function defined in the 
COMMON-LISP package. (All ANSI-defined symbols, and only those, are 
publicly defined in the COMMON-LISP package.) See 
http://www.lispworks.com/reference/HyperSpec/Body/11_abab.htm (I find 
these restrictions too extreme, but that's how it is.)

You can always get around these limitations by defining your own 
versions of the getters that you are interested in. (They can even have 
the same name when you shadow the original ones. But that's an advanced 
topic and you have to understand packages and symbols well.)

b) A function (setf cos) wouldn't do the job anyway. The function header 
for a setf function must look as follows:

(defun (setf some-function) (new-value x)
   ...)

A call (setf (some-function y) value) will be (roughly) transformed into 
(funcall #'(setf some-function) value y).  This means that the variable 
that you actually want to change (y in this example) is passed as a 
parameter to the (setf some-function) function. Since Common Lisp 
doesn't have call by reference, but only call by value for functions, 
this means that you cannot modify that variable from inside (setf 
some-function), so it's not possible to get what you want this way.

A way out would be to use DEFINE-SETF-EXPANDER. I haven't used this yet, 
and it looks hairy, so I can't help you here.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Kalle Olavi Niemitalo
Subject: Re: magic of setf
Date: 
Message-ID: <87k6xtjs0o.fsf@Astalo.kon.iki.fi>
Pascal Costanza <········@web.de> writes:

> A way out would be to use DEFINE-SETF-EXPANDER. I haven't used this
> yet, and it looks hairy, so I can't help you here.

Here's my attempt.  Can you find any bugs?

(defpackage "MY"
  (:use "COMMON-LISP")
  (:shadow "COS"))
(in-package "MY")

(declaim (inline cos))
(defun cos (number)
  (cl:cos number))

(define-setf-expander cos (angle &environment env)
  (multiple-value-bind (angle-vars angle-vals angle-store-vars
			angle-writer-form angle-reader-form)
      (get-setf-expansion angle env)
    (let* ((vars angle-vars)
	   (vals angle-vals)
	   (store-var (gensym "COS"))
	   ;; If someone does (setf (cos (values x y)) 0.5),
	   ;; then the following MULTIPLE-VALUE-BIND causes
	   ;; NIL to be stored in Y.
	   (writer-form `(multiple-value-bind ,angle-store-vars
			     (values (acos ,store-var))
			   ,angle-writer-form
			   ,store-var))
	   (reader-form `(cos ,angle-reader-form)))
      (values vars vals (list store-var) writer-form reader-form))))
From: Christopher C. Stacy
Subject: Re: magic of setf
Date: 
Message-ID: <u4qow3c8s.fsf@news.dtpq.com>
SETF is very similar to SETQ.  

In both SETQ and SETF, the first argument cases is the place 
whose value you want to set.  This argument is not evaluated.  
SETQ only understands symbols.  SETQ "magically" knows how 
to set the value of a variable named by a symbol. The second
argument, which is evaluated normally, is the new value.

SETF works much like SETQ, and has the same syntax, except that 
it knows how to set the value of more kinds of "places".
You can think of SETQ as an impovershed version of SETF.

(SETF FOO 3) does the same thing as (SETQ FOO 3).

To set the value of element I in array FOO, you would write:

(SETF (AREF FOO I) 3) 

This works because SETF has been programmed specifically to recognize
"places" that are lists whose whose CAR is the symbol AREF.
SETF looks up the corresponding "setter" routine for the case
of AREF, which produces the code needed to set the array value.

The general framework of SETF is that you can set the value V
to be returned by a reference (F X) by calling (SETF (F X) V).
This is done by specifically programming SETF to recognize (F X).
The semantics of SETF are pre-defined and arbitrary. 
You can teach SETF about new "places", providing the macro that 
will produce the code that does the actual setting.  How your macro
analyzes the given reference expression (F X) and what code it generates
to perform the work of achiecing the setting, is entirely up to you.

When you program your own SETF methods (with DEFSETF), your macro 
will produce whatever normal Lisp code you want.  By contrast, some 
of the places that SETF already knows about involve generating code
that is implementation-dependant.  For example, the code that sets a
local variable (that is, the internal guts of how SETQ works).
But that's the only thing magic about it.

>>>>> On Sat, 26 Jun 2004 22:11:13 +0200, Jim Newton ("Jim") writes:
 Jim> here is what happens when i try to set a setf method for cos.
 Jim> what's happening here?

 Jim> [1]> (defun (setf cos) ( x y) (setq x (acos y)))

There appear to be two things wrong in your example.

1. DEFUN is not how you teach SETF new tricks.
   You were miseld by someone who tried to tell you that the
   SETF mechanism works by calling a function named like that.
   (Perhaps that was a partly correct detail of how one Lisp
   compiler implementation works, under the covers.)

   The thing that you're looking for is called DEFSETF.

2. You might be confused about the syntax of SETF.
   Your original example was this:

     Jim> (setq x (acos 1))
     Jim> but i cannot say
     Jim> (setf (cos x) 1)

   I am not positive what you're trying to accomplish, but if
   you just want to set the variable X to the value of (COS 1),
   then you would write:       (SETF X (COS 1)).
   SETF is just like SETQ.

   If you were to define a SETF method for COS, that would be
   defining a way to rewrite the cosine table.  I doubt that you
   meant do to that!   Alternatively, if you were trying to establish
   some symbolic relationship between variable X and a continuous
   function or something, SETF doesn't do that either.  It's not a
   computer algebra system or anything like that.  Although you can
   program it arbitrarily, SETF is intended to merely be SETQ for storage
   locations that happen to have more complex names than just a symbol.

cheers,
Chris
From: Edi Weitz
Subject: Re: magic of setf
Date: 
Message-ID: <877jtsy3s1.fsf@bird.agharta.de>
On Sun, 27 Jun 2004 21:46:43 GMT, ······@news.dtpq.com (Christopher C. Stacy) wrote:

> 1. DEFUN is not how you teach SETF new tricks.
>    You were miseld by someone who tried to tell you that the
>    SETF mechanism works by calling a function named like that.
>    (Perhaps that was a partly correct detail of how one Lisp
>    compiler implementation works, under the covers.)
>
>    The thing that you're looking for is called DEFSETF.

According to the standard the first argument to DEFUN is a "function
name" and the dictionary says that a function name is "a symbol or a
list (SETF SYMBOL)."

I think the following code is perfectly portable ANSI Common Lisp:

  * (defun tenth (seq)
      (elt seq 9))

  TENTH
  * (defun (setf tenth) (seq new-value)
      (setf (elt seq 9) new-value))

  (SETF TENTH)
  * (defparameter *a* (list 1 2 3 4 5 6 7 8 9 10 11 12))

  *A*
  * (tenth *a*)

  10
  * (setf (tenth *a*) 42)

  42
  * *a*

  (1 2 3 4 5 6 7 8 9 42 11 12)

Of course, facilities like DEFSETF or even DEFINE-SETF-EXPANDER are
more general.

Edi.


-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Christopher C. Stacy
Subject: Re: magic of setf
Date: 
Message-ID: <uu0ww5zob.fsf@news.dtpq.com>
Oh.
:)
From: Kalle Olavi Niemitalo
Subject: Re: magic of setf
Date: 
Message-ID: <871xk0fcuf.fsf@Astalo.kon.iki.fi>
Edi Weitz <········@agharta.de> writes:

> I think the following code is perfectly portable ANSI Common Lisp:

>   * (defun (setf tenth) (seq new-value)
>       (setf (elt seq 9) new-value))

Nope, it isn't.  Functions named (setf foo) get the new value as 
the first argument [1], not the last.  Apparently, your testing 
did not reveal this bug because TENTH is a standard CL function 
and can already be used with SETF [2]; if the implementation 
uses a setf expander for this, it hides your setf function.

On the other hand, in the short form of DEFSETF, the update-fn 
gets the new value as its last argument.  I presume this makes 
it possible to convert simple SETF forms without generating 
temporary variables, expanding e.g. (setf (symbol-value foo) 42) 
to (set foo 42) rather than (let* ((#:g3986 foo) (#:g3985 42)) 
(set #:g3986 #:g3985)).  However, this simplification appears to 
be an extension not mandated by the standard, as the list of 
kinds of places [3] does not mention the short form of DEFSETF 
separately.  DEFSETF defines a setf expander [4], but 
GET-SETF-EXPANSION does not give enough information to permit 
reliably removing the temporary variables until the reader and 
writer forms have themselves been macroexpanded.

[1] section 5.1.2.9 (Other Compound Forms as Places)
[2] section 5.1.2.2 (Function Call Forms as Places)
[3] section 5.1.2 (Kinds of Places)
[4] section 5.1.2.6 (Setf Expansions and Places)
From: Edi Weitz
Subject: Re: magic of setf
Date: 
Message-ID: <87n02onn4r.fsf@bird.agharta.de>
On Mon, 28 Jun 2004 08:52:56 +0300, Kalle Olavi Niemitalo <···@iki.fi> wrote:

> Edi Weitz <········@agharta.de> writes:
>
>> I think the following code is perfectly portable ANSI Common Lisp:
>
>>   * (defun (setf tenth) (seq new-value)
>>       (setf (elt seq 9) new-value))
>
> Nope, it isn't.  Functions named (setf foo) get the new value as the
> first argument [1], not the last. [...]  On the other hand, in the
> short form of DEFSETF, the update-fn gets the new value as its last
> argument.

Argh! Yes, sorry.

Edi.


-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2ka0jmF196nq0U1@uni-berlin.de>
thanks for the response christopher, but you missed the point.
what i was trying to do with (setf (cos x) 1) was
to set x to the value such that (cos x) is 1.  it seems to me
the natural thing you would want that to do... the setf macro
should unfold (setf (cos x) 1) into the macro (setf x (acos 1)).
at least that is my opinion.  others on the group have
disagreed.

the idea that i get from reading the description of setf without
having had experience with it (as i am new to this dialect of lisp)
is that without setf you would need every reader function to have
a corresponding writer function.

aref/set-aref
slot-value/set-slot-value
get-prop/set-prop   --> sorry i do not yet know the names of the
                                       CL functions to access property
                                       lists

thus it appears to me like setf simply rewrites
(setf (slot-value a b) c) --> (set-slot-value a b c)
(setf (aref a b) c)       --> (set-aref a b c)

there seem to be an association of function/inverse along with
function-syntax/inverse-syntax which setf knows how to handle.

My assumption, (which apparently was wrong) was that i could
register with setf the funtion/inverse pair cos/acos and the
associated syntax.

It seems logicial TO ME that setf could unfold
(setf (cos x) y)   into (setf x (acos y))

-jim

Christopher C. Stacy wrote:
> SETF is very similar to SETQ.  
> 
> In both SETQ and SETF, the first argument cases is the place 
> whose value you want to set.  This argument is not evaluated.  
> SETQ only understands symbols.  SETQ "magically" knows how 
> to set the value of a variable named by a symbol. The second
> argument, which is evaluated normally, is the new value.
> 
> SETF works much like SETQ, and has the same syntax, except that 
> it knows how to set the value of more kinds of "places".
> You can think of SETQ as an impovershed version of SETF.
> 
> (SETF FOO 3) does the same thing as (SETQ FOO 3).
> 
> To set the value of element I in array FOO, you would write:
> 
> (SETF (AREF FOO I) 3) 
> 
> This works because SETF has been programmed specifically to recognize
> "places" that are lists whose whose CAR is the symbol AREF.
> SETF looks up the corresponding "setter" routine for the case
> of AREF, which produces the code needed to set the array value.
> 
> The general framework of SETF is that you can set the value V
> to be returned by a reference (F X) by calling (SETF (F X) V).
> This is done by specifically programming SETF to recognize (F X).
> The semantics of SETF are pre-defined and arbitrary. 
> You can teach SETF about new "places", providing the macro that 
> will produce the code that does the actual setting.  How your macro
> analyzes the given reference expression (F X) and what code it generates
> to perform the work of achiecing the setting, is entirely up to you.
> 
> When you program your own SETF methods (with DEFSETF), your macro 
> will produce whatever normal Lisp code you want.  By contrast, some 
> of the places that SETF already knows about involve generating code
> that is implementation-dependant.  For example, the code that sets a
> local variable (that is, the internal guts of how SETQ works).
> But that's the only thing magic about it.
> 
> 
>>>>>>On Sat, 26 Jun 2004 22:11:13 +0200, Jim Newton ("Jim") writes:
> 
>  Jim> here is what happens when i try to set a setf method for cos.
>  Jim> what's happening here?
> 
>  Jim> [1]> (defun (setf cos) ( x y) (setq x (acos y)))
> 
> There appear to be two things wrong in your example.
> 
> 1. DEFUN is not how you teach SETF new tricks.
>    You were miseld by someone who tried to tell you that the
>    SETF mechanism works by calling a function named like that.
>    (Perhaps that was a partly correct detail of how one Lisp
>    compiler implementation works, under the covers.)
> 
>    The thing that you're looking for is called DEFSETF.
> 
> 2. You might be confused about the syntax of SETF.
>    Your original example was this:
> 
>      Jim> (setq x (acos 1))
>      Jim> but i cannot say
>      Jim> (setf (cos x) 1)
> 
>    I am not positive what you're trying to accomplish, but if
>    you just want to set the variable X to the value of (COS 1),
>    then you would write:       (SETF X (COS 1)).
>    SETF is just like SETQ.
> 
>    If you were to define a SETF method for COS, that would be
>    defining a way to rewrite the cosine table.  I doubt that you
>    meant do to that!   Alternatively, if you were trying to establish
>    some symbolic relationship between variable X and a continuous
>    function or something, SETF doesn't do that either.  It's not a
>    computer algebra system or anything like that.  Although you can
>    program it arbitrarily, SETF is intended to merely be SETQ for storage
>    locations that happen to have more complex names than just a symbol.
> 
> cheers,
> Chris
From: Rahul Jain
Subject: Re: magic of setf
Date: 
Message-ID: <87pt7jdwnb.fsf@nyct.net>
Jim Newton <·····@rdrop.com> writes:

> the idea that i get from reading the description of setf without
> having had experience with it (as i am new to this dialect of lisp)
> is that without setf you would need every reader function to have
> a corresponding writer function.

Actually, the setf expansion's "writer" return value is the writer
function that is used by SETF. It's just a way to make the setters and
getters look more similar so that users need only learn one name, not
two, and so that more complex modifier macros may be implemented
efficiently (e.g., not having to search a data structure for the exact
location that's requested twice: once for the get and then for the set
of the modified value).

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Mark McConnell
Subject: Re: magic of setf
Date: 
Message-ID: <d3aed052.0406290939.56cc4c1@posting.google.com>
Jim Newton <·····@rdrop.com> wrote in message news:<···············@uni-berlin.de>...
> thanks for the response christopher, but you missed the point.
> what i was trying to do with (setf (cos x) 1) was
> to set x to the value such that (cos x) is 1.  it seems to me
> the natural thing you would want that to do... the setf macro
> should unfold (setf (cos x) 1) into the macro (setf x (acos 1)).

setf doesn't invert a mathematical algorithm.  It inverts a sequence
of look-ups in data structures.

Other people in the group have explained it better, but I'm trying to
reduce it to an aphorism.

Here is a variation on what you want.  Hope I'm not going off on a
tangent.

(defmacro invert-math ((math-func arg) value)
  (ecase math-func
    (cos `(setf ,arg (acos ,value))
    (sin `(setf ,arg (asin ,value))
    (tan `(setf ,arg (atan ,value)))))

(invert-math (cos x) 1) ;; binds x to 0.0

(invert-math (sin x) 1/2) ;; binds x to 0.5235988 = 30 deg

And because invert-math is based on setf, it can dig inside data
structures.

(defvar qq '(15 16))

(invert-math (sin (car qq)) 1/2) ;; now qq = (0.5235988 16)
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2kdtgcF17q79U1@uni-berlin.de>
hey that's pretty cool.


Mark McConnell wrote:
> Jim Newton <·····@rdrop.com> wrote in message news:<···············@uni-berlin.de>...
> 
>>thanks for the response christopher, but you missed the point.
>>what i was trying to do with (setf (cos x) 1) was
>>to set x to the value such that (cos x) is 1.  it seems to me
>>the natural thing you would want that to do... the setf macro
>>should unfold (setf (cos x) 1) into the macro (setf x (acos 1)).
> 
> 
> setf doesn't invert a mathematical algorithm.  It inverts a sequence
> of look-ups in data structures.
> 
> Other people in the group have explained it better, but I'm trying to
> reduce it to an aphorism.
> 
> Here is a variation on what you want.  Hope I'm not going off on a
> tangent.
> 
> (defmacro invert-math ((math-func arg) value)
>   (ecase math-func
>     (cos `(setf ,arg (acos ,value))
>     (sin `(setf ,arg (asin ,value))
>     (tan `(setf ,arg (atan ,value)))))
> 
> (invert-math (cos x) 1) ;; binds x to 0.0
> 
> (invert-math (sin x) 1/2) ;; binds x to 0.5235988 = 30 deg
> 
> And because invert-math is based on setf, it can dig inside data
> structures.
> 
> (defvar qq '(15 16))
> 
> (invert-math (sin (car qq)) 1/2) ;; now qq = (0.5235988 16)
From: Pascal Bourguignon
Subject: Re: magic of setf
Date: 
Message-ID: <87n02mgmmt.fsf@thalassa.informatimago.com>
···············@yahoo.com (Mark McConnell) writes:
> Here is a variation on what you want.  Hope I'm not going off on a
> tangent.
> 
> (defmacro invert-math ((math-func arg) value)
>   (ecase math-func
>     (cos `(setf ,arg (acos ,value))
>     (sin `(setf ,arg (asin ,value))
>     (tan `(setf ,arg (atan ,value)))))
> 
> (invert-math (cos x) 1) ;; binds x to 0.0

Wrong, it should bind x to (* 2 pi), or to (* 2 k pi) for any k in Z.

What does he really want? 


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

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Mark McConnell
Subject: Re: magic of setf
Date: 
Message-ID: <d3aed052.0406300830.5d721eea@posting.google.com>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> ···············@yahoo.com (Mark McConnell) writes:
> > Here is a variation on what you want.  Hope I'm not going off on a
> > tangent.
> > 
> > (defmacro invert-math ((math-func arg) value)
> >   (ecase math-func
> >     (cos `(setf ,arg (acos ,value))
> >     (sin `(setf ,arg (asin ,value))
> >     (tan `(setf ,arg (atan ,value)))))
> > 
> > (invert-math (cos x) 1) ;; binds x to 0.0
> 
> Wrong, it should bind x to (* 2 pi), or to (* 2 k pi) for any k in Z.
> 
> What does he really want?

Fortunately, Lisp lets you return multiple values.
From: William Bland
Subject: Re: magic of setf
Date: 
Message-ID: <pan.2004.06.30.16.44.30.253094@abstractnonsense.com>
On Wed, 30 Jun 2004 09:30:03 -0700, Mark McConnell wrote:

> Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
>> ···············@yahoo.com (Mark McConnell) writes:
>> > Here is a variation on what you want.  Hope I'm not going off on a
>> > tangent.
>> > 
>> > (defmacro invert-math ((math-func arg) value)
>> >   (ecase math-func
>> >     (cos `(setf ,arg (acos ,value))
>> >     (sin `(setf ,arg (asin ,value))
>> >     (tan `(setf ,arg (atan ,value)))))
>> > 
>> > (invert-math (cos x) 1) ;; binds x to 0.0
>> 
>> Wrong, it should bind x to (* 2 pi), or to (* 2 k pi) for any k in Z.
>> 
>> What does he really want?
> 
> Fortunately, Lisp lets you return multiple values.

But not an infinite number of them, surely?  Unless there's some way
you can make the list of return values lazy?

Cheers,
	Bill.
-- 
Dr. William Bland.
It would not be too unfair to any language to refer to Java as a
stripped down Lisp or Smalltalk with a C syntax.   (Ken Anderson).
From: Christopher C. Stacy
Subject: Re: magic of setf
Date: 
Message-ID: <u8ye5c6l0.fsf@news.dtpq.com>
>>>>> On Wed, 30 Jun 2004 16:44:01 GMT, William Bland ("William") writes:

 William> On Wed, 30 Jun 2004 09:30:03 -0700, Mark McConnell wrote:
 >> Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
 >>> ···············@yahoo.com (Mark McConnell) writes:
 >>> > Here is a variation on what you want.  Hope I'm not going off on a
 >>> > tangent.
 >>> > 
 >>> > (defmacro invert-math ((math-func arg) value)
 >>> >   (ecase math-func
 >>> >     (cos `(setf ,arg (acos ,value))
 >>> >     (sin `(setf ,arg (asin ,value))
 >>> >     (tan `(setf ,arg (atan ,value)))))
 >>> > 
 >>> > (invert-math (cos x) 1) ;; binds x to 0.0
 >>> 
 >>> Wrong, it should bind x to (* 2 pi), or to (* 2 k pi) for any k in Z.
 >>> 
 >>> What does he really want?
 >> 
 >> Fortunately, Lisp lets you return multiple values.

 William> But not an infinite number of them, surely?

At least 20 values are allowed, beyond that it's 
implementation dependant.  MULTIPLE-VALUES-LIMIT.
From: André Thieme
Subject: Re: magic of setf
Date: 
Message-ID: <cbvug4$4lk$1@ulric.tng.de>
William Bland schrieb:

>>Fortunately, Lisp lets you return multiple values.
> 
> 
> But not an infinite number of them, surely?

This is very certain.
I think even (fac (fac 1000)) is too much.

:-)


Andr�
--
From: Barry Margolin
Subject: Re: magic of setf
Date: 
Message-ID: <barmar-BCA2D7.01123801072004@comcast.dca.giganews.com>
In article <············@ulric.tng.de>,
 Andr� Thieme <······························@justmail.de> wrote:

> William Bland schrieb:
> 
> >>Fortunately, Lisp lets you return multiple values.
> > 
> > 
> > But not an infinite number of them, surely?
> 
> This is very certain.
> I think even (fac (fac 1000)) is too much.
> 
> :-)

It may be a big number, but it's still only *one* value.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Hannah Schroeter
Subject: Re: magic of setf
Date: 
Message-ID: <cbuds6$4jj$1@c3po.use.schlund.de>
Hello!

Mark McConnell <···············@yahoo.com> wrote:
>[...]

>(defvar qq '(15 16))

>(invert-math (sin (car qq)) 1/2) ;; now qq = (0.5235988 16)

Or it lets demons fly out of your nose. [1]

Kind regards,

Hannah.

[1] Modifying a quoted constant causes undefined effects.
From: Mark McConnell
Subject: Re: magic of setf
Date: 
Message-ID: <d3aed052.0406301239.7dad33d2@posting.google.com>
······@schlund.de (Hannah Schroeter) wrote in message news:<············@c3po.use.schlund.de>...
> Hello!
> 
> Mark McConnell <···············@yahoo.com> wrote:
> >[...]
>  
> >(defvar qq '(15 16))
>  
> >(invert-math (sin (car qq)) 1/2) ;; now qq = (0.5235988 16)
> 
> Or it lets demons fly out of your nose. [1]
> 
> Kind regards,
> 
> Hannah.
> 
> [1] Modifying a quoted constant causes undefined effects.

(defvar qq '(mouth))
(rplaca qq 'foot)

Thanks for the correction.  :-)
From: Mark McConnell
Subject: Re: magic of setf
Date: 
Message-ID: <d3aed052.0406301240.4549a079@posting.google.com>
······@schlund.de (Hannah Schroeter) wrote in message news:<············@c3po.use.schlund.de>...
> Hello!
> 
> Mark McConnell <···············@yahoo.com> wrote:
> >[...]
>  
> >(defvar qq '(15 16))
>  
> >(invert-math (sin (car qq)) 1/2) ;; now qq = (0.5235988 16)
> 
> Or it lets demons fly out of your nose. [1]
> 
> Kind regards,
> 
> Hannah.
> 
> [1] Modifying a quoted constant causes undefined effects.

(defvar qq '(mouth))
(rplaca qq 'foot)

Thanks for catching the mistake.  :-)
From: Jim Newton
Subject: Re: magic of setf
Date: 
Message-ID: <2ka0pfF18n5hsU1@uni-berlin.de>
> 1. DEFUN is not how you teach SETF new tricks.
>    You were miseld by someone who tried to tell you that the
>    SETF mechanism works by calling a function named like that.
>    (Perhaps that was a partly correct detail of how one Lisp
>    compiler implementation works, under the covers.)
> 
>    The thing that you're looking for is called DEFSETF.
> 


I took the syntax (defun (setf ....) ...) from a new book
i've bought called "Object-Oriented Common Lisp" by Stephen
Slade.  It seems like a great book.  It is sort of a tutorial.
As i am already familiar with other lisp dialects, but just not
CL, it seem to be a great book, and i'd recommend it to other
people as well.

-jim
From: Alan Crowe
Subject: Re: magic of setf
Date: 
Message-ID: <86acymjh9p.fsf@cawtech.freeserve.co.uk>
Christopher C. Stacy time warped thus:
> 1. DEFUN is not how you teach SETF new tricks.
>    You were miseld by someone who tried to tell you that the
>    SETF mechanism works by calling a function named like that.
>    (Perhaps that was a partly correct detail of how one Lisp
>    compiler implementation works, under the covers.)
>
>    The thing that you're looking for is called DEFSETF.

Sorry Christopher, but they changed the language underneath
you. Quoting from page 100 of ANSI Common Lisp by Paul
Graham:

    By making the first argument to DEFUN a list of the form
    (SETF f), you define what happens when the first
    argument to SETF is a call to f. The following pair of
    functions defines PRIMO as a synonym for CAR:

    (defun primo (lst)(car lst))

    (defun (setf primo)(val lst)
      (setf (car lst) val))

Graham has an end note:

    In older Common Lisp implementations, you have to use
    DEFSETF to define how a call should be treated when it
    appears as the first argument to SETF. Be careful when
    translating, because the parameter representing the new
    value cames /last/ in the definition of a function whose
    name is given as the second argument to DEFSETF.

Issue FUNCTION-NAME Writeup page HyperSpec/Issues/iss174_w.htm
makes interesting reading.

This might be a good time to mention one of my favourite
nice little details in CL.

Suppose you are writing a routine that is supposed to deal
with arrays of any rank. How do you read the elements? Do
you have to do

(case rank
	(1 (aref a i))
	(2 (aref a i j))
	(3 (aref a i j k)) ....

Happily no. AREF is a function and you can apply it to a
list of indices

(defun my-general-rank-routine( &rest list-of-indices )
   ...
   (apply #'aref list-of-indices)
   ...

Ah, that's all very well, but what about writing them.
That was forseen and 

   (setf (apply #'aref .... ))

is specified to work in 5.1.2.5 APPLY Forms as Places
http://www.franz.com/support/documentation/6.2/ansicl/subsubse/applyfor.htm

It is reasonable to expect that a symmetric n by n matrix is
stored in 1/2 n(n+1) rather than n^2 locations. CL doesn't
have a symetric matrix type so you write your own.

(defun sym-mat-ref(a i j)
  (let ((n (max i j))
        (m (min i j)))
    (aref a (+ (ash (* n (+ n 1)) -1) m))))

(defun (setf sym-mat-ref)(item a i j)
  (let ((n (max i j))
        (m (min i j)))
    (setf (aref a (+ (ash (* n (+ n 1)) -1) m))
          item)))

Then the question arises: can you do

(setf (apply #'sym-mat-ref index-list))

Reading to the end of 5.1.2.5 APPLY Forms as Places
we find:

      If a user-defined function is used in this context,
      the following equivalence is true, except that care is
      taken to preserve proper left-to-right evaluation of
      argument subforms:

       (setf (apply #'name {arg}*) val)
       ==(apply #'(setf name) val {arg}*)
  
So yes you can. It is specified in the standard, and our own
portable accessors can have the same sophisticated
capabilities for handling varible numbers of arguments as
the built in AREF, and it works for writing, not just
reading. I love that kind of do-the-right-thing
attention-to-detail in a computer language.

Alan Crowe
Edinburgh
Scotland
From: Pascal Bourguignon
Subject: Re: magic of setf
Date: 
Message-ID: <878yea2bp6.fsf@thalassa.informatimago.com>
Jim Newton <·····@rdrop.com> writes:

> but i see that i can increase the data base of what setf
> knows how to do.
> 
> (defun (setf x) ( y z)
>    ...)
> 
> can i use this to make setf work with cos and acos?

Because the values of cos or acos change over time perhaps?


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

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: JP Massar
Subject: Re: magic of setf
Date: 
Message-ID: <197sd0h46bu87n54sd1dp0tcmhpquqpgaa@4ax.com>
On 27 Jun 2004 00:31:33 +0200, Pascal Bourguignon
<····@thalassa.informatimago.com> wrote:

>Jim Newton <·····@rdrop.com> writes:
>
>> but i see that i can increase the data base of what setf
>> knows how to do.
>> 
>> (defun (setf x) ( y z)
>>    ...)
>> 
>> can i use this to make setf work with cos and acos?
>
>Because the values of cos or acos change over time perhaps?

I think he wants

(setf (cos x) 1) --> (setq x (acos 1))

(It's not clear to me why he would want such a thing, aside from
the initial comment about an 'inverter' function.  SETF really isn't
an 'inverter' function, and I think he has a misunderstanding as
to what SETF is supposed to be doing)
From: David Sletten
Subject: Re: magic of setf
Date: 
Message-ID: <FUmDc.3267$ju5.675@twister.socal.rr.com>
Jim Newton wrote:
> hi.  i've been using a dialect of list for several years before
> being introduced to common lisp.  this dialect had no setf, but
> rather used set and setq, so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.  but it does not
> always seem to work as i'd expect.
> 
> for example i can say
> 
> (setq x (acos 1))
> 
> but i cannot say
> 
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined
> 
> Can someone explain to me what setf really does?
> 
> -jim
> 
You seem to expect SETF to work along the lines of certain Prolog 
procedures, e.g.:
conc([], L, L).
conc([X|L1], L2, [X|L3]) :- conc(L1, L2, L3).

Thus,
?- conc([a, b], [c, d], L).
yields L = [a, b, c, d]

Whereas,
?- conc(L1, L2, [a, b, c]).
results in
L1 = []
L2 = [a, b, c];

L1 = [a]
L2 = [b, c];

etc...

However, SETF does not compute any sort of function inversion. I take it 
that your SETF example is trying to store in the variable X that angle 
at which cos(X) is 1. This is not how SETF works. As others have pointed 
out, SETF is really just a souped-up version of SETQ. It has a different 
kind of magic than what you were expecting.

David Sletten
From: Pascal Costanza
Subject: Re: magic of setf
Date: 
Message-ID: <cbko34$gju$1@newsreader2.netcologne.de>
Jim Newton wrote:

> hi.  i've been using a dialect of list for several years before
> being introduced to common lisp.  this dialect had no setf, but
> rather used set and setq, so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.  but it does not
> always seem to work as i'd expect.
> 
> for example i can say
> 
> (setq x (acos 1))
> 
> but i cannot say
> 
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined
> 
> Can someone explain to me what setf really does?

SETF cannot guess what it should do in order to achieve it's effect. 
Instead, it should rather be thought of as a framework that you can 
extend in order to support your own setters. Common Lisp just "happens" 
to have quite a number of setters already defined.

The assocation between a getter and a setter roughly works like this: 
SETF is a macro that analyzes its first (unevaluated) parameter in order 
to see if it denotes a known getter. It then looks up the appropriate 
setter, and replaces the SETF form with a call to that setter. (This is 
a very rough sketch, the details are somewhat more hairy.)

For details, see http://www.lispworks.com/reference/HyperSpec/Body/05_a.htm


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Rahul Jain
Subject: Re: magic of setf
Date: 
Message-ID: <87fz8hltnj.fsf@nyct.net>
Jim Newton <·····@rdrop.com> writes:

> hi.  i've been using a dialect of list for several years before
> being introduced to common lisp.  this dialect had no setf, but
> rather used set and setq, so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.  but it does not
> always seem to work as i'd expect.

I have no clue what that is supposed to mean. It doesn't invert
anything. It just allows you to set the value that would conceptually be
returned by some code to some new value. In other words, (setf <form>
<value>) should arrange for <form> to evaluate to <value>.

> for example i can say
>
> (setq x (acos 1))
>
> but i cannot say
>
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined

You're asking to set the cosine of whatever X is bound to at run-time to
be 1. Huh?

> Can someone explain to me what setf really does?

This has been explained by others, but there are other modify-macros
that use the full setf-expansion system. For example, INCF and PUSH.

Also, see DEFINE-MODIFY-MACRO.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Alan Crowe
Subject: Re: magic of setf
Date: 
Message-ID: <86u0wxnt58.fsf@cawtech.freeserve.co.uk>
Jim Newton wrote:
> this dialect had no setf, but rather used set and setq, so
> the magic of setf seems a bit overwhelming to me.  I'm not
> sure i really understand what it does.  It acts sort of
> like a symbolic algebra inversion mechanism.  but it does
> not always seem to work as i'd expect.

I think you are hoping for much more from setf than it
actually delivers. In C, the syntax of a l-value is much the
same as that of an r-value, so you can write

a[i] = b[j]+c[k];

setf is doing basically the same job.

(setf (aref a i)
      (+ (aref b j)
         (aref c k)))

One important programming technique is wrapping your data
structures up in accessors functions. This gives you freedom
to change the implementation of your data structures without
rewriting the programs that use them.

A trivial example might represent the results of an Olympic
race as a list, and use accessors

(defun gold (race)(car race))
(defun silver(race)(cadr race))
(defun bronze(race)(caddr race))
(defvar *race* '(al bill chris dave))

(silver *race*) => BILL

But William objects to being called Bill.
Do we have to fix it with

(setf (cadr *race*) 'william)?

That would make a nonsense of wrapping the data structures
in accessor functions. CL lets us define writers as well as
readers

(defun (setf gold)(runner race)
(defun (setf silver)(runner race)
(defun (setf bronze)(runner race)

Now we can setf our access functions

(setf (silver *race*) 'william)
*race* => (AL WILLIAM CHRIS DAVE)

and Bill, sorry, William, is happy.

Notice a subtle point. CL passes arguments by value, but
does so without any copying of data structures. So functions
can poke about in the guts of data structures that are given
to them, and my examples work. When we try

(defun sine(angle)
  (sin angle))

(defun (setf sine)(angle value)
    (setf angle (asin value)))

(defvar *theta* 0)

(setf (sine *theta*) 0.5)

*theta* => 0

It hasn't worked. The function (setf sine) only changed its
local copy of angle. We aren't stuck.

(fmakunbound '(setf sine)) ; get rid of old definition
(defmacro invert-sine (place value) ; new one has to be a macro
     `(setf ,place (asin ,value)))
(defsetf sine invert-sine) ; tell setf about it

(setf (sine *theta*) 0.5)
*theta* => 0.5235988

Yes! It works. But are we winning? 

My gut feeling, based on inadequate experience with CL is

1)doing (defun (setf gold)...) to make access functions work
  with setf is a very useful technique. 

2)If you are not "inverting" an accessor, there is no
  genuine connection to setf. You would be much better off
  with code like

(defmacro inverse (function &rest args)
    `(,(case function
	     (sin 'asin)
	     (cos 'acos)
	     (square 'sqrt))
      ,@args))

(inverse cos 1) => 0.0
(inverse square 25) => 5.0
(setf *theta* (inverse sin 1))
*theta* => 1.5707964

That keeps the functional concept of an inverse function
distinct from the notion of assignment.

Alan Crowe
Edinburgh
Scotland
From: Kalle Olavi Niemitalo
Subject: Re: magic of setf
Date: 
Message-ID: <871xk0kgw0.fsf@Astalo.kon.iki.fi>
Alan Crowe <····@cawtech.freeserve.co.uk> writes:

> (setf (sine *theta*) 0.5)
> *theta* => 0.5235988
>
> Yes! It works. But are we winning?

Unfortunately, it doesn't quite work.  In SBCL 0.8.11:

* (macroexpand-1 '(incf (sine *theta*) 0.1))
(LET* ((#:G4135 *THETA*) (#:G4134 (+ (SINE #:G4135) 0.1)))
  (INVERT-SINE #:G4135 #:G4134))
T

That will not change the value of *THETA*.

If I understand correctly, your definition

> (defmacro invert-sine (place value) ; new one has to be a macro
>      `(setf ,place (asin ,value)))
> (defsetf sine invert-sine) ; tell setf about it

violates the same rule as the more concise

  (defsetf sine (place) (value)
    `(setf ,place (asin ,value)))

but somehow SBCL expands them in different ways, so that the 
simple case (setf (sine *theta*) 0.5) works with the former but 
not with the latter.  More complex cases like INCF or SHIFTF 
fail with both.
From: Joerg Hoehle
Subject: Re: magic of setf
Date: 
Message-ID: <uy8lo8761.fsf@users.sourceforge.net>
Jim Newton <·····@rdrop.com> writes:

> so the magic of setf seems a bit overwhelming
> to me.  I'm not sure i really understand what it does.  It acts sort
> of like a symbolic algebra inversion mechanism.

No, and it cannot be used as such -- see below.

> but it does not always seem to work as i'd expect.
> (setq x (acos 1))
> but i cannot say
> (setf (cos x) 1)
> *** - EVAL: the function (SETF COS) is undefined

Others have explained to you DEFSETF, DEFINE-MODIFY-MACRO,
setf-expanders and more. However, your initial goal is not appropriate
for SETF.  Proof by counterexample:
What would you expect
	(setf (cos (fact x)) 1) to do?
To expand into (setf (fact x) (acos 1)) 
  and hope that (setf fact) is defined as well?

This can be done, but if that's your expectation, then I recommend you
to look for a constraint propagation system or some such.

I hope this example suffices to show you that a (setf cos) would be
too limited to be useful. It may still be fun to play with & learn from.

Hint for macro writers: think about what expansions should look like
in complex cases, i.e. not with literals or variables.

> Can someone explain to me what setf really does?
Others did this already.

	Jorg Hohle
Telekom/T-Systems Technology Center