I have a question about setf and structures.
I'm trying to figure out how to pass into a mapping function
a function that selects which slot of a structure to update.
For example, assume:
(defstruct thing x y z)
(setq *things* (list (make-thing :x 5) (make-thing :x 10) (make-thing :x 15)))
To retrieve the values of the x slot of each structure I can do
the following, where I pass in a structure access function to
specify which slot to retrieve from:
(mapcar #'thing-x *things*) => (5 10 15)
Okay. Now how do I do the same thing to *set* the slots?
I want to do something like this:
(mapc #'set-thing-x *things* '(8 12 16)) => sets :x slots to 8, 12, 16, respectively
Since setting values uses (setf (thing-x <structure>) <value>),
I don't see how the setf form can be passed to the mapping function.
Do I have to actually define a "set-thing-x" function (and similar
functions for the other slots) just for this purpose?
(defun set-thing-x (structure value)
(setf (thing-x structure) value))
In other words, what is the "name" of the structure update function so
that I can pass it to a mapping function? I'd like to know the answer
for Common Lisp and, if you're familiar with it, Interleaf Lisp, the
dialect I'm working with currently--it's similar to but not identical
with Common Lisp.
Thanks in advance for your answer.
- Bob Beal
········@tasb.org
In article <...> ········@tasb.org (Bob Beal) writes:
>
> I have a question about setf and structures.
>
> I'm trying to figure out how to pass into a mapping function
> a function that selects which slot of a structure to update.
>
> For example, assume:
>
> (defstruct thing x y z)
> (setq *things* (list (make-thing :x 5) (make-thing :x 10) (make-thing :x 15)))
>
> Okay. Now how do I do the same thing to *set* the slots?
> I want to do something like this:
>
> (mapc #'set-thing-x *things* '(8 12 16)) => sets :x slots to 8, 12, 16, respectively
>
> Since setting values uses (setf (thing-x <structure>) <value>),
> I don't see how the setf form can be passed to the mapping function.
The standard metaphor for doing this is to use an anonymous function
introduced with lambda:
(mapc #'(lambda (s v) (setf (thing-x s) v)) *things* '(8 12 16))
> Do I have to actually define a "set-thing-x" function (and similar
> functions for the other slots) just for this purpose?
More or less, this is correct, but you don't have to name them.
> In other words, what is the "name" of the structure update function so
> that I can pass it to a mapping function? I'd like to know the answer
> for Common Lisp and, if you're familiar with it, Interleaf Lisp, the
> dialect I'm working with currently--it's similar to but not identical
> with Common Lisp.
I'm not familiar with Interleaf Lisp, but lambda is a pretty basic part
of lisp.
--
Thomas A. Russ, USC/Information Sciences Institute ···@isi.edu
In article <··········@aplcenmp.apl.jhu.edu> ····@aplcenmp.apl.jhu.edu (Marty Hall) writes:
From: ····@aplcenmp.apl.jhu.edu (Marty Hall)
Newsgroups: comp.lang.lisp
Date: Wed, 28 Feb 1996 13:50:19 GMT
Organization: JHU/APL Research Center, Hopkins P/T CS Faculty
References: <··········@gatekeeper.tasb.org>
Distribution: inet
Lines: 41
In article <··········@gatekeeper.tasb.org> ········@tasb.org writes:
[...]
>(defstruct thing x y z)
>(setq *things* (list (make-thing :x 5) (make-thing :x 10) (make-thing :x 15)))
[...]
>Okay. Now how do I do the same thing to *set* the slots?
>I want to do something like this:
>
>(mapc #'set-thing-x *things* '(8 12 16)) => sets :x slots to 8, 12, 16
(I tried emailing but it bounced)
I assume you already know you could do
(mapc #'(lambda (Thing X-Val) (setf (thing-x Thing) X-Val))
*things*
'(8 12 16))
>In other words, what is the "name" of the structure update function so
>that I can pass it to a mapping function?
With CLOS generic functions, the name of the function is actually
(setf XXX) if there is an accessor of that form. Eg:
(defclass Foo ()
((A :initform 4 :accessor A)))
(setq *Foos*
(list (make-instance 'Foo) (make-instance 'Foo) (make-instance 'Foo)))
(mapcar #'A *Foos*) --> (4 4 4)
(mapc #'(setf A) '(5 6 7) *Foos*) ; Note values first, objects second
(mapcar #'A *Foos*) --> (5 6 7)
Actually the #'(setf thing-x) works directly also for CL (at least
CMUCL which is CLtL2-ANSI friendly).
* (defstruct thing x y z)
THING
* (setq *things* (list (make-thing :x 5) (make-thing :x 10) (make-thing :x 15)))
(#S(THING :X 5 :Y NIL :Z NIL) #S(THING :X 10 :Y NIL :Z NIL)
#S(THING :X 15 :Y NIL :Z NIL))
* (mapc #'(setf thing-x) '( 8 12 16) *things*)
(8 12 16)
* *things*
(#S(THING :X 8 :Y NIL :Z NIL) #S(THING :X 12 :Y NIL :Z NIL)
#S(THING :X 16 :Y NIL :Z NIL))
*
Note the inversion of the arguments. The setters in CL want the value
first and the object next. Don't ask me why.
But I doubt you will have anything like this with Interleaf Lisp, so
stick with the lambda-form method there.
Yep. Don't know about Interleaf Lisp.
Cheers
--
Marco Antoniotti - Resistente Umano
===============================================================================
International Computer Science Institute | ·······@icsi.berkeley.edu
1947 Center STR, Suite 600 | tel. +1 (510) 643 9153
Berkeley, CA, 94704-1198, USA | +1 (510) 642 4274 x149
===============================================================================
...it is simplicity that is difficult to make.
...e` la semplicita` che e` difficile a farsi.
Bertholdt Brecht
From: David B. Kuznick
Subject: Re: Q: setf and structures
Date:
Message-ID: <DnLJos.6qz@ci.com>
In article <···············@salmon.ICSI.Berkeley.EDU>, ·······@salmon.icsi.berkeley.edu (Marco Antoniotti) writes:
|> Actually the #'(setf thing-x) works directly also for CL (at least
|> CMUCL which is CLtL2-ANSI friendly).
|>
|> * (defstruct thing x y z)
|> THING
|> * (setq *things* (list (make-thing :x 5) (make-thing :x 10) (make-thing :x 15)))
|> (#S(THING :X 5 :Y NIL :Z NIL) #S(THING :X 10 :Y NIL :Z NIL)
|> #S(THING :X 15 :Y NIL :Z NIL))
|> * (mapc #'(setf thing-x) '( 8 12 16) *things*)
|> (8 12 16)
|> * *things*
|> (#S(THING :X 8 :Y NIL :Z NIL) #S(THING :X 12 :Y NIL :Z NIL)
|> #S(THING :X 16 :Y NIL :Z NIL))
It may work in CMUCL, but as far as I know it's not guaranteed to work in any
Common Lisp per se.