From: ··@flash.bellcore.com
Subject: updating random slots in (say) defstruct
Date:
Message-ID: <18837@bellcore.bellcore.com>
Given something like:
(defstruct test
(one)
(two)
(three))
one can do something like
(setq access-function 'test-one)
(setq instance (make-test :one 1 :two 2 :three 3))
(funcall access-function instance) => 1
There appears to be no Common LISP way to similarly update a random
slot. The best one can do seems to be:
(defun update-slot (object slot value)
(case slot
(one (setf (test-one object) value)
....
))
Must i explicitly define my structure as say a list, to be able to
replace an arbitrary component? Symbolics documentation on LOCFs is a
little sketchy, but perhaps i can use them?
Ideas?
Peter Clitherow
From: Barry Margolin
Subject: Re: updating random slots in (say) defstruct
Date:
Message-ID: <32860@news.Think.COM>
In article <·····@bellcore.bellcore.com> ··@flash.bellcore.com writes:
>There appears to be no Common LISP way to similarly update a random
>slot. The best one can do seems to be:
You can do
(setq updater-function #'(lambda (object value)
(setf (test-one object) value)))
(funcall updater-function instance value)
In ANSI Common Lisp you'll be able to use #'(setf test-one) to access the
updater function directly.
--
Barry Margolin, Thinking Machines Corp.
······@think.com
{uunet,harvard}!think!barmar
In article <·····@bellcore.bellcore.com> ··@flash.bellcore.com writes:
[defstruct deleted]
>There appears to be no Common LISP way to similarly update a random
>slot [of a structure]. The best one can do seems to be:
[example using 'case' deleted]
>Must i explicitly define my structure as say a list, to be able to
>replace an arbitrary component? Symbolics documentation on LOCFs is a
>little sketchy, but perhaps i can use them?
>
>Ideas?
This is handled on page 96 of CLtL (1st ed.), which discusses setf.
That is section 7.2, (setf), seventh bullet, in case paginations differ.
It is legal to say (setf (apply #'fn args) newval).
In this case, one could say something like:
(setf instance (make-fubar :one 'a :two 'b :three 'c))
(setf accessor #'fubar-one) ; note use of #' here
(setf (apply accessor (list instance)) newvalue)
to change the :one slot of instance to newvalue.
The book warns that this works only if the setf method for the function
is of a normal kind, i.e. produces an update function that resembles the
access function except for having a final argument added which is the new value.
So the solution is somewhat implementation dependent, but should work
on any "reasonable" implementation. (I have not tested it past one
implementation.)
From: Jeff Dalton
Subject: Re: updating random slots in (say) defstruct
Date:
Message-ID: <1571@skye.ed.ac.uk>
In article <·············@marob.masa.com> ·····@marob.masa.com (John Cowan) writes:
>In article <·····@bellcore.bellcore.com> ··@flash.bellcore.com writes:
>>Must i explicitly define my structure as say a list, to be able to
>>replace an arbitrary component?
>This is handled on page 96 of CLtL (1st ed.), which discusses setf.
>That is section 7.2, (setf), seventh bullet, in case paginations differ.
>It is legal to say (setf (apply #'fn args) newval).
>In this case, one could say something like:
> (setf instance (make-fubar :one 'a :two 'b :three 'c))
> (setf accessor #'fubar-one) ; note use of #' here
> (setf (apply accessor (list instance)) newvalue)
>to change the :one slot of instance to newvalue.
What CLtL says is that SETF will work for a call to APPLY provided
that (1) APPLY's first argument has the form #'function-name and
(2) calls to function-name are recognized as places by SETF.
That is, to be able to do
(setf (apply #'f ...apply-args...) y)
you have to be able to do
(setf (f ...args...) y)
In your example above, ACCESSOR would not be recognized as a place
by SETF, nor do you write #'ACCESSOR. So
(setf (apply accessor ...) ...)
probably won't work. On the other hand,
(setf (apply #'fubar-one ...) ...)
looks like it ought to work. Unfortunately it doesn't in any of the
Common Lisps I've tried.
>The book warns that this works only if the setf method for the function
>is of a normal kind, i.e. produces an update function that resembles the
>access function except for having a final argument added which is the new
>value.
That's probably it. Presumably nothing says the SETF methods for
structure slot accessors have the required property. Too bad if so.
>So the solution is somewhat implementation dependent, but should work
>on any "reasonable" implementation. (I have not tested it past one
>implementation.)
Does (SETF (APPLY ACCESSOR ...) ...) really work somewhere?
-- Jeff
From: Barry Margolin
Subject: Re: updating random slots in (say) defstruct
Date:
Message-ID: <32964@news.Think.COM>
In article <·············@marob.masa.com> ·····@marob.masa.com (John Cowan) writes:
> (setf (apply accessor (list instance)) newvalue)
No, this isn't valid. The first argument to APPLY when it is being used as
a SETF place must be a constant. SETF is a macro, so it must know at
expansion time what the accessor is so that it can expand into a call to
the corresponding updater.
>(I have not tested it past one implementation.)
If it works, it's due to an implementation extension. It doesn't work on
my Symbolics system or in Lucid CL; the latter gives the error "SETF of
APPLY is only defined for function args like #'symbol."
--
Barry Margolin, Thinking Machines Corp.
······@think.com
{uunet,harvard}!think!barmar