From: Delaregue
Subject: setf
Date: 
Message-ID: <6b4aa54a.0209020820.6deec1e6@posting.google.com>
Hello,

I am having problems to understand why the following does not work:

(defmethod employee-retrieve ((c company) val &key field)
  (loop for emps in (employees c)
        if (equal (funcall field emps) val)
        collect emps))
=>#<STANDARD-METHOD EMPLOYEE-RETRIEVE NIL (COMPANY T) 205EAB8C>

(employee-retrieve *company*  0 :field #'id)
=>(#<EMPLOYEE 213550DC>)

(defmethod employee-edit ((emp employee) val &key field)
 (setf (funcall field emp) val))
=>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>

(employee-edit 
 (first (employee-retrieve *company*  0 :field #'id)) 
 "whatevever" :field #'lastname)
=>Undefined function (SETF FIELD) called with arguments ("whatever"
#<EMPLOYEE 213550DC>).

Can you tell me why?

From: Thomas F. Burdick
Subject: Re: setf
Date: 
Message-ID: <xcvk7m42ui6.fsf@hurricane.OCF.Berkeley.EDU>
·········@netscape.net (Delaregue) writes:

> Hello,
> 
> I am having problems to understand why the following does not work:
> 
> (defmethod employee-retrieve ((c company) val &key field)
>   (loop for emps in (employees c)
>         if (equal (funcall field emps) val)
>         collect emps))
> =>#<STANDARD-METHOD EMPLOYEE-RETRIEVE NIL (COMPANY T) 205EAB8C>
> 
> (employee-retrieve *company*  0 :field #'id)
> =>(#<EMPLOYEE 213550DC>)
> 
> (defmethod employee-edit ((emp employee) val &key field)
>  (setf (funcall field emp) val))
> =>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>
> 
> (employee-edit 
>  (first (employee-retrieve *company*  0 :field #'id)) 
>  "whatevever" :field #'lastname)
> =>Undefined function (SETF FIELD) called with arguments ("whatever"
> #<EMPLOYEE 213550DC>).
> 
> Can you tell me why?

As has already been said, the function in (setf (funcall function ...) ...)
needs to be statically determinable at compile-time.  In fact, it
needs to be of the form: (setf (funcall #'function ...) ...).

Now, you probably want to know how to do what you were trying to do.
The answer is to pass in both a reader and a writer function.  So:

  (defgeneric employee-edit (emp val &key field-reader field-writer))

Of course, this means you'd need to call it like this:

  (employee-edit employee "new-val" :field-reader #'lastname
                                    :field-writer #'(setf lastname))

which is a pain.  You can, though, wrap your calls in a macro that
takes a place argument, and expands appropriately.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kenny Tilton
Subject: Re: setf
Date: 
Message-ID: <3D7455F6.4000009@nyc.rr.com>
Thomas F. Burdick wrote:
> ·········@netscape.net (Delaregue) writes:
> 
> 
>>Hello,
>>
>>I am having problems to understand why the following does not work:
>>
>>(defmethod employee-retrieve ((c company) val &key field)
>>  (loop for emps in (employees c)
>>        if (equal (funcall field emps) val)
>>        collect emps))
>>=>#<STANDARD-METHOD EMPLOYEE-RETRIEVE NIL (COMPANY T) 205EAB8C>
>>
>>(employee-retrieve *company*  0 :field #'id)
>>=>(#<EMPLOYEE 213550DC>)
>>
>>(defmethod employee-edit ((emp employee) val &key field)
>> (setf (funcall field emp) val))
>>=>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>
>>
>>(employee-edit 
>> (first (employee-retrieve *company*  0 :field #'id)) 
>> "whatevever" :field #'lastname)
>>=>Undefined function (SETF FIELD) called with arguments ("whatever"
>>#<EMPLOYEE 213550DC>).
>>
>>Can you tell me why?

Rough guess: use slot-value (and(setf slot-value)) for this kinda stuff.

kenny
From: Barry Margolin
Subject: Re: setf
Date: 
Message-ID: <KS4d9.7$QK1.457@paloalto-snr1.gtei.net>
In article <················@nyc.rr.com>,
Kenny Tilton  <·······@nyc.rr.com> wrote:
>Rough guess: use slot-value (and(setf slot-value)) for this kinda stuff.

While this will usually work, it's not generally a good solution, because
it only works for classes that use the default accessors.  If a subclass
defines its own accessor methods, or has before/after/around methods for
the accessors, slot-value will bypass them.

-- 
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: Paul F. Dietz
Subject: Re: setf
Date: 
Message-ID: <3D739749.3809E128@dls.net>
Delaregue wrote:

> (defmethod employee-edit ((emp employee) val &key field)
>  (setf (funcall field emp) val))
> =>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>

Setf needs to know the accessor at compile time, but
field only has a value at run time.

	Paul
From: Frode Vatvedt Fjeld
Subject: Re: setf
Date: 
Message-ID: <2hadn0s5cq.fsf@vserver.cs.uit.no>
·········@netscape.net (Delaregue) writes:

> I am having problems to understand why the following does not work:
>
> (defmethod employee-retrieve ((c company) val &key field)
>   (loop for emps in (employees c)
>         if (equal (funcall field emps) val)
>         collect emps))
> =>#<STANDARD-METHOD EMPLOYEE-RETRIEVE NIL (COMPANY T) 205EAB8C>
>
> (employee-retrieve *company*  0 :field #'id)
> =>(#<EMPLOYEE 213550DC>)
>
> (defmethod employee-edit ((emp employee) val &key field)
>  (setf (funcall field emp) val))
> =>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>
>
> (employee-edit 
>  (first (employee-retrieve *company*  0 :field #'id)) 
>  "whatevever" :field #'lastname)
> =>Undefined function (SETF FIELD) called with arguments ("whatever"
> #<EMPLOYEE 213550DC>).
>
> Can you tell me why?

There is no explicit connection between a reader function and the
associated writer function. So when you pass the "lastname" reader
function as a parameter to employee-edit, there is (almost) no way to
figure out what is the writer-function that should be called. The form
(setf (funcall field emp) val) is to the best of my knowledge not
legal CL.

You must decide whether you want to pass functions or slot-names
around. You could do this:

  (defmethod employee-edit ((emp employee) val &key field)
    (funcall field val emp))

  (employee-edit (first (employee-retrieve *company*  0 :field #'id)) 
    "whatevever" :field #'(setf lastname))
  => "whatever"

Most likely a better strategy would be to refer to slots by their
names:

  (defmethod employee-retrieve ((c company) val &key field)
    (loop for emps in (employees c)
          if (equal (slot-value emps field) val)
          collect emps))
  =>#<STANDARD-METHOD EMPLOYEE-RETRIEVE NIL (COMPANY T) 205EAB8C>

  (employee-retrieve *company* 0 :field 'id)
  =>(#<EMPLOYEE 213550DC>)

  (defmethod employee-edit ((emp employee) val &key field)
    (setf (slot-value emp field) val))
  =>#<STANDARD-METHOD EMPLOYEE-EDIT NIL (EMPLOYEE T) 205EAD1C>

  (employee-edit 
   (first (employee-retrieve *company* 0 :field 'id)) 
   "whatevever" :field 'lastname)
  => "whatever"

I haven't tested this, there might be some editing mistakes.

-- 
Frode Vatvedt Fjeld
From: Delaregue
Subject: Re: setf
Date: 
Message-ID: <6b4aa54a.0209030151.399bc967@posting.google.com>
Thanks for the answers. It has also helped me to put some light on
what :accessor do when declaring a slot in a class.