From: Andrew Lawson
Subject: (setf method), tricks and manipulation
Date: 
Message-ID: <slrndteq2m.qoi.adl@adl.vm.bytemark.co.uk>
Hello
    Although I've been programming in lisp for a while it's only lately
I've been playing with CLOS. This has led to some confusion over method
definition and particularly setf. Here's a quick semi-example that
hopefully shows the issue

Imagine I have a function that does something to an object, it both has
to read slots and set slot values and i want it to do so via the
appropriate accessors. The function therefore needs to know three
things, the object, the reader  and the writer. Imagining that i've used
':accessor my-accessor' in the class definition, I could  write;

(defun do-something (an-object reader-fn writer-fn)
    (funcall reader-fn an-object)
    ...
    (funcall writer-fn new-value an-object)
    ...)

And then call it as;

(do-something my-object #'my-accessor #'(setf my-accessor))

This however seems a waste of a parameter, surely I can work out the
setf version from the non-setf version, or if not, what if I supplied
the method name, is there an easy way of getting both methods from that
without having to construct the setf method name in some horribly
contrived manner and then extracting the function value from that
symbol. I suppose my question is, am I right in thinking that setf makes
writing code that does not know the name of the method in advance much
harder or am I just missing a couple of simple tricks?

        thanks

                Andrew

From: Frode Vatvedt Fjeld
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <2hlkx44j50.fsf@vserver.cs.uit.no>
Andrew Lawson <···@absentis.com> writes:

> surely I can work out the setf version from the non-setf version,

No, in general you can't.

> or if not, what if I supplied the method name, is there an easy way
> of getting both methods from that without having to construct the
> setf method name in some horribly contrived manner and then
> extracting the function value from that symbol.

This is possible, but not very nice. Something like

  (fdefinition `(setf ,reader-name))

> I suppose my question is, am I right in thinking that setf makes
> writing code that does not know the name of the method in advance
> much harder or am I just missing a couple of simple tricks?

There is no inherent binding between the concept of slot
readers/writers and the different kinds of function
names. I.e. there's nothing but programmer convention that says "foo"
is a reader where "(setf foo)" is a writer. It is fully possible that
"foo" is a writer while "(setf foo)" is a reader, or any other
combination of names. Also note that any number of readers and writers
can be associated with a particular slot.

Perhaps you can pass the slot-name around rather than the accessors,
so that you can do (slot-value slot-name) and (setf (slot-value
slot-name) valueq)? If this is not suiable, you're probably best off
passing both the reader and writer, even if this might seem
redundant. (I think the point is: if it really _is_ redundant, then
you should pass the slot-name, otherwise not.)

-- 
Frode Vatvedt Fjeld
From: Andrew Lawson
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <slrndterkb.qtc.adl@adl.vm.bytemark.co.uk>
On 2006-01-25, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> Andrew Lawson <···@absentis.com> writes:
>
>> surely I can work out the setf version from the non-setf version,
>
> No, in general you can't.

I had the feeling that might be the case, but the hyperspec can be
impenetrable when you're arfter things like this.

>> or if not, what if I supplied the method name, is there an easy way
>> of getting both methods from that without having to construct the
>> setf method name in some horribly contrived manner and then
>> extracting the function value from that symbol.
>
> This is possible, but not very nice. Something like
>
>   (fdefinition `(setf ,reader-name))
>

I had ended up doing this but I thought it too ugly to be the *right*
way :) how wrong I was

>> I suppose my question is, am I right in thinking that setf makes
>> writing code that does not know the name of the method in advance
>> much harder or am I just missing a couple of simple tricks?
>
> There is no inherent binding between the concept of slot
> readers/writers and the different kinds of function
> names. I.e. there's nothing but programmer convention that says "foo"
> is a reader where "(setf foo)" is a writer. It is fully possible that
> "foo" is a writer while "(setf foo)" is a reader, or any other
> combination of names. Also note that any number of readers and writers
> can be associated with a particular slot.
>
> Perhaps you can pass the slot-name around rather than the accessors,
> so that you can do (slot-value slot-name) and (setf (slot-value
> slot-name) valueq)? If this is not suiable, you're probably best off
> passing both the reader and writer, even if this might seem
> redundant. (I think the point is: if it really _is_ redundant, then
> you should pass the slot-name, otherwise not.)

Well, I can at least stop worrying, thanks for clarifying things.

        Andrew
From: Frode Vatvedt Fjeld
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <2hhd7s4iia.fsf@vserver.cs.uit.no>
On 2006-01-25, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:

>>   (fdefinition `(setf ,reader-name))

Andrew Lawson <···@absentis.com> writes:

> I had ended up doing this but I thought it too ugly to be the
> *right* way :) how wrong I was

Just to make sure we're on the same page, I believe that 99.9% of the
time this is indeed the wrong way.. and 100.0% of the time it's quite
ugly.

-- 
Frode Vatvedt Fjeld
From: Andrew Lawson
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <slrndtevat.r18.adl@adl.vm.bytemark.co.uk>
On 2006-01-25, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> On 2006-01-25, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
>
>>>   (fdefinition `(setf ,reader-name))
>
> Andrew Lawson <···@absentis.com> writes:
>
>> I had ended up doing this but I thought it too ugly to be the
>> *right* way :) how wrong I was
>
> Just to make sure we're on the same page, I believe that 99.9% of the
> time this is indeed the wrong way.. and 100.0% of the time it's quite
> ugly.
>
Just to give a real example of what I'd doing. I'm writing several
dialogs, none of them complex, a few text fields each. I've found that
in each case I simply want to copy the data from my model to the
interface and then on 'ok' I just want to copy the new data back to the
model. For each interface I write

(defmethod model->interface ((m model-type) (i interface-type))
    (setf (text (text-control-1 i)) (accessor-1 m)
          (text (text-control-2 i)) (accessor-2 m)))

and

(defmethod interface->model ((i interface-type) (m model-type))
    (setf (accessor-1 m) (text (text-control-1 i))
          (accessor-2 m) (text (text-control-2 i))))

The methods are normally much larger but not more complex (there are
some date fields but nothing worse) so it's boilerplate code.
I've therefore written a macro that looks like

(define-model-interface-interaction (model-type interface-type)
    (accessor-1 text-control-1)
    (accessor-2 text-control-2))

And underneath this dispatches to various methods that understand the
real type of the controls and the data in the model and does appropriate
data conversions (date->string etc ..) and as you can imagine has to get
hold of the reader and writer methods from the names of the accessors
given. this is actually working very nicely now but I'd happily hear any
ideas people have.

    Andrew
From: Thomas A. Russ
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <ymiek2wf53e.fsf@sevak.isi.edu>
Re:  #'accessor #'(setf accessor)

Well, if all you are doing is using the default accessors that defclass
produces from the :accessor keyword, then the simplest solution is to go
the route of SLOT-VALUE.  Then you just need to pass the name of the
slot.  (This was suggested in passing in some other replies).

Then you can write code like:

   (defun manipulate-slot (object my-slot-name)
       (print (slot-value object my-slot-name))
       ...
       (setf (slot-value object my-slot-name) ...)
       ...)

And call it like  (manipulate-slot my-object 'slot-22)

The only operational benefit to using the accessor and setf of the
accessor functions is that it makes it possible to have more
sophisticated methods that do something more than just read or write the
slot (for example, updating related slots, value validation, etc.)

If you want that, then you really need to pass the methods and it is
generally easier to just specify both than to derive them from the
symbol. 

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Frode Vatvedt Fjeld
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <2hd5ig47ud.fsf@vserver.cs.uit.no>
Andrew Lawson <···@absentis.com> writes:

> The methods are normally much larger but not more complex (there are
> some date fields but nothing worse) so it's boilerplate code.
> I've therefore written a macro that looks like
> 
> (define-model-interface-interaction (model-type interface-type)
>     (accessor-1 text-control-1)
>     (accessor-2 text-control-2))

I this context I think that so long as you ensure the mapping from
accessor-name to reader and writer-names occurs at
macroexpansion-time, this is proper use of macros. The macro's
semantics then is that the accessor parameter is a symbol that must
name a reader in the "normal" function namespace and the corresponding
writer in the setf namespace.

So your expander looks something like

   ... (setf (,accessor foo) bar) ...

and not e.g.

   ... (funcall ,(fdefinition (list 'setf accessor)) bar foo) ...

or anything silly like that.

-- 
Frode Vatvedt Fjeld
From: Ivan Boldyrev
Subject: Re: (setf method), tricks and manipulation
Date: 
Message-ID: <eqima3-3km.ln1@ibhome.cgitftp.uiggm.nsc.ru>
On 9365 day of my life Andrew Lawson wrote:
> Imagine I have a function that does something to an object, it both has
> to read slots and set slot values and i want it to do so via the
> appropriate accessors. The function therefore needs to know three
> things, the object, the reader  and the writer. Imagining that i've used
> ':accessor my-accessor' in the class definition, I could  write;
>
> (defun do-something (an-object reader-fn writer-fn)
>     (funcall reader-fn an-object)
>     ...
>     (funcall writer-fn new-value an-object)
>     ...)
>
> And then call it as;
>
> (do-something my-object #'my-accessor #'(setf my-accessor))
>
> This however seems a waste of a parameter...

Google for "lisp locatives".  You can find some implementation of
locatives at message

Message-ID: <························@g14g2000cwa.googlegroups.com>
(9 Dec 2005 at comp.lang.lisp)

or another version at

<http://www.hexapodia.net/pipermail/small-cl-src/2004-June/000016.html>

Locatives use #'my-accessor and #'(setf my-accessor) behind the
schene, but you shouldn't care :)

Your code will look like (using Lars Brinkoff's version):

(defun something (loc)
  (contents loc)
  ...
  (setf (contents loc) new-value))

and call it as:

(do-something (locf (my-accessor obj)))

where CONTENTS and LOCF are provide by Lars' code.

-- 
Ivan Boldyrev

                                       XML -- new language of ML family.