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
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
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
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
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
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
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
>
>
>
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
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
>
>
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."
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))))
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
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")
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)
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")
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
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
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)
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)
···············@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
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.
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).
>>>>> 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.
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�
--
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 ***
> 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
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
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
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)
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
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."
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
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
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.
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