From: Fernando Rodr�guez
Subject: Trouble with setf and slot accessor function
Date: 
Message-ID: <4m74au47bk3dd6gsfdp7ojusa1bbrkumsn@4ax.com>
I have a simple structure like this:
(defstruct node
  (name nil)
  (yes nil)
  (no nil))

And I want to write a to update a node instance:

(defun update (node-instance accessor)
  (setf (funcall accessor node-instance) 'XYZ))

so i can (update #'node-yes a-node) or (update #'node-name a-node)

I get the following error:
Couldn't find a setf expansion for (FUNCALL ACCESSOR CONCEPT).

How can I fix this? O:-)

TIA 



-----------------------
Fernando Rodriguez

From: Coby Beck
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <ybqo8.176248$eb.8862723@news3.calgary.shaw.ca>
"Fernando Rodr�guez" <····@wanadoo.es> wrote in message
·······································@4ax.com...
>
> I have a simple structure like this:
> (defstruct node
>   (name nil)
>   (yes nil)
>   (no nil))
>
> And I want to write a to update a node instance:
>
> (defun update (node-instance accessor)
>   (setf (funcall accessor node-instance) 'XYZ))
>

Does this fit the bill?

CL-USER 17 > (setf foo (make-node))
#S(NODE NAME NIL YES NIL NO NIL)

CL-USER 18 > (defun update-node (node slot value)
              (setf (slot-value node slot) value))
UPDATE-NODE

CL-USER 19 > (update-node foo 'name "Yes")
"Yes"

CL-USER 20 > (update-node foo 'yes "it")
"it"

CL-USER 21 > (update-node foo 'no "works")
"works"

CL-USER 22 > foo
#S(NODE NAME "Yes" YES "it" NO "works")


--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Barry Margolin
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <%6ro8.19$vU1.50@paloalto-snr2.gtei.net>
In article <·······················@news3.calgary.shaw.ca>,
Coby Beck <·····@mercury.bc.ca> wrote:
>
>"Fernando Rodr�guez" <····@wanadoo.es> wrote in message
>·······································@4ax.com...
>>
>> I have a simple structure like this:
>> (defstruct node
>>   (name nil)
>>   (yes nil)
>>   (no nil))
>>
>> And I want to write a to update a node instance:
>>
>> (defun update (node-instance accessor)
>>   (setf (funcall accessor node-instance) 'XYZ))
>>
>
>Does this fit the bill?
>
>CL-USER 17 > (setf foo (make-node))
>#S(NODE NAME NIL YES NIL NO NIL)
>
>CL-USER 18 > (defun update-node (node slot value)
>              (setf (slot-value node slot) value))
>UPDATE-NODE

There's no requirement that SLOT-VALUE work for DEFSTRUCT slots.  It's only
defined for CLOS slots.  You're making use of an implementation-specific
extension.

Of course, it should be simple for the OP to change from using DEFSTRUCT to
DEFCLASS, and then he could do what he wants.

To the OP: the Lisp FAQ addresses this issue in some detail.  I know,
because this is one of the questions that prompted me to write the FAQ
about a decade ago.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Wolfhard Buß
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <m37knxg35q.fsf@buss-14250.user.cis.dfn.de>
Fernando Rodr�guez <····@wanadoo.es> writes:

> I have a simple structure like this:
> (defstruct node
>   (name nil)
>   (yes nil)
>   (no nil))
> 
> And I want to write a to update a node instance:
> 
> (defun update (node-instance accessor)
>   (setf (funcall accessor node-instance) 'XYZ))

> How can I fix this? O:-)


 (defmacro update (node-instance accessor value)
   `(setf (,accessor ,node-instance) ,value))

might help. Lookup defsetf, define-modify-macro ... in CLHS.

-- 
"Das Auto hat keine Zukunft. Ich setze aufs Pferd."  Wilhelm II. (1859-1941)
From: Coby Beck
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <mmro8.176282$eb.8874949@news3.calgary.shaw.ca>
"Wolfhard Bu�" <·····@gmx.net> wrote in message
···················@buss-14250.user.cis.dfn.de...
> Fernando Rodr�guez <····@wanadoo.es> writes:
>
> > I have a simple structure like this:
> > (defstruct node
> >   (name nil)
> >   (yes nil)
> >   (no nil))
> >
> > And I want to write a to update a node instance:
> >
> > (defun update (node-instance accessor)
> >   (setf (funcall accessor node-instance) 'XYZ))
>
> > How can I fix this? O:-)
>
>
>  (defmacro update (node-instance accessor value)
>    `(setf (,accessor ,node-instance) ,value))
>

That only works if accessor is known at macroexpansion time, ie is not a
variable name but one of NAME, YES or NO.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Kenny Tilton
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <3CA39E40.346D9ED8@nyc.rr.com>
> 
> Fernando Rodr�guez <····@wanadoo.es> writes:
> 
> > I have a simple structure like this:
> > (defstruct node
> >   (name nil)
> >   (yes nil)
> >   (no nil))
> >
> > And I want to write a to update a node instance:
> >
> > (defun update (node-instance accessor)
> >   (setf (funcall accessor node-instance) 'XYZ))
> 
> > How can I fix this? O:-)
> 

Just curious: what is wrong with:

   (setf (node-name <node>) <value)

? BTW, even getting this to work:

    (update <node> <slot-name> <value>) ;; I cannot believe you mean to
hard-code the new value

...would be against the grain of Lisp, you would want the syntax to be:

    (update (<slot-name> <node>) <value>)

...but in Lisp update is called setf, so we're back to:

    (setf (<accessor> <node>) <value>)

Now I /do/ have code that says:

    (defun set-obsolete (node) (setf (node-status node) :obsolete))

...so I can change that if necessary to:

    (defun set-obsolete (node) (setf (obsolete-p node) t))

...and then I get all Lisp-y and create:

    (defun (setf obsolete-p node) (setf (valid node) nil)) ;; just to
show implementation is hidden
    (defun obsolete-p (node) (null (valid node)))

Sorry for rambling on, but your query left a lot of questions so I was
not sure where you were going with this.

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Don't you just hate it when you run out of ice?"
                                             Arthur (RIP)
From: Kenny Tilton
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <3CA40887.84A9B972@nyc.rr.com>
Kenny Tilton wrote:

> ...and then I get all Lisp-y and create:
> 
>     (defun (setf obsolete-p node) (setf (valid node) nil)) ;; just to
> show implementation is hidden

oops. should be:

(defun (setf obsolete-p) (new-state node)
    ; but then this is a dumb example...

  kenny tilton
  clinisys, inc
  ---------------------------------------------------------------
 "Don't you just hate it when you run out of ice?"
                                              Arthur (RIP)
From: Fernando Rodr�guez
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <j1n8au8smcumtion2ucme7jbdp0hk8jcva@4ax.com>
On Thu, 28 Mar 2002 22:47:02 GMT, Kenny Tilton <·······@nyc.rr.com> wrote:

>> 
>> Fernando Rodr�guez <····@wanadoo.es> writes:
>> 
>> > I have a simple structure like this:
>> > (defstruct node
>> >   (name nil)
>> >   (yes nil)
>> >   (no nil))
>> >
>> > And I want to write a to update a node instance:
>> >
>> > (defun update (node-instance accessor)
>> >   (setf (funcall accessor node-instance) 'XYZ))
>> 
>> > How can I fix this? O:-)
>> 
>
>Just curious: what is wrong with:
>
>   (setf (node-name <node>) <value)

>Sorry for rambling on, but your query left a lot of questions so I was
>not sure where you were going with this.

The examle I gave was over-simplified and probably not a very good one. The
real 'update' function only modifies certain slots if a given number of
conditions are satisfied. Of course I could hard-code all the setfs in the
function that calls 'update', but it would be a bit ugly.




-----------------------
Fernando Rodriguez
From: Kent M Pitman
Subject: Re: Trouble with setf and slot accessor function
Date: 
Message-ID: <sfwu1qvhjby.fsf@shell01.TheWorld.com>
Fernando Rodr�guez <····@wanadoo.es> writes:

> I have a simple structure like this:
> (defstruct node
>   (name nil)
>   (yes nil)
>   (no nil))
> 
> And I want to write a to update a node instance:
> 
> (defun update (node-instance accessor)
>   (setf (funcall accessor node-instance) 'XYZ))
> 
> so i can (update #'node-yes a-node) or (update #'node-name a-node)

[You flipped your argument order here.]

I don't think that DEFSTRUCT is defined to guarantee you the use of
funcallable methods for the access, so as a consequence, the following
may or may not work, depending on the implementation:

(defun update (node-instance accessor new-value)
  (funcall (fdefinition `(setf ,accessor)) new-value node-instance))
 
(update a-node 'node-yes 'xyz)

You must use the symbol, not the function, in order for the funcall
of (SETF NODE-YES) to work.

If you changed this to be a DEFCLASS instead of a DEFSTRUCT,  you would
get this ability.  But then, if you'd used DEFCLASS, you could also
just use SETF of SYMBOL-VALUE on the individual slot names, which is
even better...

> I get the following error:
> Couldn't find a setf expansion for (FUNCALL ACCESSOR CONCEPT).
> 
> How can I fix this? O:-)

If you want to just use ANSI CL and you need DEFSTRUCT and you want
not rely on details of the MOP, the traditional way is something like:

(defmacro my-defstruct (struct-name &rest slot-specs)
  (let* ((slot-names (mapcar #'car slot-specs))
         (accessor-names (mapcar #'(lambda (name)
                                     (concatenate 'string 
                                       (symbol-name struct-name) 
                                       "-"
                                       (symbol-name slot-name)))
                                 slot-names)))
    `(progn 
       (defstruct ,struct-name ,@slot-specs)
       ,@(mapcan #'(lambda (slot-name accessor-name)
                     (list
                       (defmethod struct-slot ((struct ,struct-name)
                                               (key (eql ',slot-name)))
                         (,accessor-name struct))
                       (defmethod (setf struct-slot) 
                                  (value
                                   (struct ,struct-name)
                                   (key (eql ',slot-name)))
                         (setf (,accessor-name struct) value))))
                 slot-names
                 accessor-names)
       ',struct-name)))

[I didn't test this.]