From: ···@netvision.net.il
Subject: Q: (setf (funcall ...) (...))
Date: 
Message-ID: <335CF1A7.4B82@netvision.net.il>
Hello.
My question has two parts.
I am trying to pass a class accessor name as a parameter to a function
that does the actual accessing.

> (defclass myclass ()
    ((member1 :accessor member1 :initform '(a a) :initarg :member1)
     (member2 :accessor member2 :initform '(b b) :initarg :member2)))
> (setf myinstance (make-instance 'myclass))

I found out that I can do it by applying 'funcall' to the accessor name.

> (defun class-assoc (object member-t)
  (funcall member-t object))
> (class-assoc myinstance 'member1)

My first question is if there is a better, more correct way of doing 
it, or is this way good enough ?

Now to the second part of the question.
I am trying to use the above 'class-assoc' in combination with setf
but I recieve an error.

> (defun myassert (object member-t) 
   (setf
         (class-assoc object member-t)
         '(c c)))
> (myassert myinstance 'member1)

;;Error: Symbol #:\(SETF\ CLASS-ASSOC\) passed to SYMBOL-FUNCTION should
have a global function definition in MYASSERT

I guess it might have to do with the 'setf' macro expansion ??
Why does it happen ? What am I doing wrong ? 
I am using Freelisp and ACL.
Thanx for taking the time to answer.
	Gary

From: Barry Margolin
Subject: Re: Q: (setf (funcall ...) (...))
Date: 
Message-ID: <5jk5o1$h5m@pasilla.bbnplanet.com>
In article <·············@netvision.net.il>,  <···@netvision.net.il> wrote:
>> (defun class-assoc (object member-t)
>  (funcall member-t object))
>> (class-assoc myinstance 'member1)
>
>My first question is if there is a better, more correct way of doing 
>it, or is this way good enough ?

You should probably be using #'member1, but otherwise this is the right way
to do it.  The only alternative is calling SLOT-VALUE, but that makes your
code overly dependent on the fact that the accessor directly accesses a
slot.  Calling the generic function is better, because it allows you to
reimplement the accessor as a function without having to change the calling
code.


>Now to the second part of the question.
>I am trying to use the above 'class-assoc' in combination with setf
>but I recieve an error.
>
>> (defun myassert (object member-t) 
>   (setf
>         (class-assoc object member-t)
>         '(c c)))
>> (myassert myinstance 'member1)
>
>;;Error: Symbol #:\(SETF\ CLASS-ASSOC\) passed to SYMBOL-FUNCTION should
>have a global function definition in MYASSERT
>
>I guess it might have to do with the 'setf' macro expansion ??
>Why does it happen ? What am I doing wrong ? 

You never did (define-set-method class-assoc ...) or (defsetf class-assoc
...).  You need to use this to tell SETF how it should process an
assignment like this.

Your Subject line suggests that you expect SETF to look at the definition
of CLASS-ASSOC and "figure it out" automatically.  The only time that SETF
will do this is when the definition is a macro -- SETF expands the macro
invocation and then acts as if you'd entered that originally.  If the
definition is a function, it's treated as a black box, and it's up to the
programmer to tell it how to do the assignment.
-- 
Barry Margolin
BBN Corporation, Cambridge, MA
······@bbnplanet.com
(BBN customers, call (800) 632-7638 option 1 for support)
From: Thomas A. Russ
Subject: Re: Q: (setf (funcall ...) (...))
Date: 
Message-ID: <ymiiv1dy70h.fsf@hobbes.isi.edu>
In article <·············@netvision.net.il> ···@netvision.net.il writes:
 > Hello.
 > My question has two parts.
 > I am trying to pass a class accessor name as a parameter to a function
 > that does the actual accessing.
 > 
 >> (defclass myclass ()
 >     ((member1 :accessor member1 :initform '(a a) :initarg :member1)
 >      (member2 :accessor member2 :initform '(b b) :initarg :member2)))
 >> (setf myinstance (make-instance 'myclass))
 > 
 > I found out that I can do it by applying 'funcall' to the accessor name.
 > 
 >> (defun class-assoc (object member-t)
 >   (funcall member-t object))
 >> (class-assoc myinstance 'member1)
 > 
 > My first question is if there is a better, more correct way of doing 
 > it, or is this way good enough ?

As Barry Margolin notes in a separate reply, this is a reasonable and
flexible way of doing the access.  The alternate way would be to use the
built-in function SLOT-VALUE directly in place of your class assoc method:

  (slot-value myinstance 'member1)

 > Now to the second part of the question.
 > I am trying to use the above 'class-assoc' in combination with setf
 > but I recieve an error.

Using SLOT-VALUE works fine with setf, so for your particular
application, it may make sense to give up the flexibility of using the
slot accessor.  Essentially, the flexibiltiy you give up is the option
of reimplementing the slot as a function.

 >> (defun myassert (object member-t) 
 >    (setf
 >          (class-assoc object member-t)
 >          '(c c)))

(defun myassert (object member-t)
  (setf (slot-value object member-t) '(c c)))

 >> (myassert myinstance 'member1)

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Stefan k. Bamberger
Subject: Re: Q: (setf (funcall ...) (...))
Date: 
Message-ID: <bambi-2404971424220001@wi6a84.informatik.uni-wuerzburg.de>
The use of slot-value is possible in the general case, but it's less
efficient than the explicit reader and writer methods (at least in my lisp
implementation).

I suggest the following code:


(defclass my-test ()
  ((slot1 :initform 3 :accessor sl1)
   (slot2 :initform 'a :accessor sl2)
   )
  )


(defun general-read (object reader)
  (funcall reader object)
  )

(defun general-write (object writer value)
  (funcall (symbol-function `(setf ,writer)) value object)
  )

#|
(setq foo (make-instance 'mein-test))

(general-read foo 'sl1)
(general-write foo 'sl1 6)
|#

If you want to use the same function for reading wnd writing, then try this:

(defun general-access (object read-method)
  (general-read object read-method))

(defsetf general-access general-write)

#|
(setq foo (make-instance 'mein-test))

(general-access foo 'sl1)
(setf (general-access foo 'sl1) 1)
|#

For this approach it is necessary that you use an accessor-method
otherwise the computation of the writer-method will fail.
If you only have the slot-name and don't know whether a reader and/or
writer method exists you can adapt the code above, checking for such a
method with:

(slot-readers (class-of foo) 'slot1)
(slot-writers (class-of foo) 'slot1)

But then, I suppose, slot-value will be faster again ;-))

- stefan



In article <···············@hobbes.isi.edu>, ···@isi.edu wrote:

> In article <·············@netvision.net.il> ···@netvision.net.il writes:
>  > Hello.
>  > My question has two parts.
>  > I am trying to pass a class accessor name as a parameter to a function
>  > that does the actual accessing.
>  > 
>  >> (defclass myclass ()
>  >     ((member1 :accessor member1 :initform '(a a) :initarg :member1)
>  >      (member2 :accessor member2 :initform '(b b) :initarg :member2)))
>  >> (setf myinstance (make-instance 'myclass))
>  > 
>  > I found out that I can do it by applying 'funcall' to the accessor name.
>  > 
>  >> (defun class-assoc (object member-t)
>  >   (funcall member-t object))
>  >> (class-assoc myinstance 'member1)
>  > 
>  > My first question is if there is a better, more correct way of doing 
>  > it, or is this way good enough ?
> 
> As Barry Margolin notes in a separate reply, this is a reasonable and
> flexible way of doing the access.  The alternate way would be to use the
> built-in function SLOT-VALUE directly in place of your class assoc method:
> 
>   (slot-value myinstance 'member1)
> 
>  > Now to the second part of the question.
>  > I am trying to use the above 'class-assoc' in combination with setf
>  > but I recieve an error.
> 
> Using SLOT-VALUE works fine with setf, so for your particular
> application, it may make sense to give up the flexibility of using the
> slot accessor.  Essentially, the flexibiltiy you give up is the option
> of reimplementing the slot as a function.
> 
>  >> (defun myassert (object member-t) 
>  >    (setf
>  >          (class-assoc object member-t)
>  >          '(c c)))
> 
> (defun myassert (object member-t)
>   (setf (slot-value object member-t) '(c c)))
> 
>  >> (myassert myinstance 'member1)
> 
> -- 
> Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu
-- 
University of Wuerzburg, GERMANY
·····@informatik.uni-wuerzburg.de