From: Bob Beal
Subject: Q: setf and structures
Date: 
Message-ID: <4h0950$quo@gatekeeper.tasb.org>
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

From: Thomas A. Russ
Subject: Re: Q: setf and structures
Date: 
Message-ID: <TAR.96Feb28133027@hobbes.ISI.EDU>
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    
From: Marco Antoniotti
Subject: Re: Q: setf and structures
Date: 
Message-ID: <s08ka15bt8p.fsf@salmon.ICSI.Berkeley.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.