From: Oleksandr Kozachuk
Subject: Slots
Date: 
Message-ID: <slrnaajqet.8pt.Alex@Tron.ddeus.lan>
Hi all!

I need help with slots.

(defclass test () ((v1 :accessor test-v1)))

Now this work correct:

(setq a (make-instance 'test))
(setf (test-v1 a) 2)
(test-v1 a)

=> 2

But on "setf" it must call a funktion, but this _DONT WORK_:

(defclass test () ((v1 :accessor test-v1 :writer test-v1-set)))
(defmethod test-v1-set ((self test) (data number))
    (setf (slot-value self 'v1) (+ data 1)))

(setq a (make-instance 'test))
(setf (test-v1 a) 2)
(test-v1 a)

=> 2 (why???)

How can i change the data?

Maybe anything like this (dont work):

(defmethod (setf test-v1) ((self test) (data number))
    (setf (slot-value self 'v1) (+ data 1)))


Thank you for help.

Alex.

From: Nils Goesche
Subject: Re: Slots
Date: 
Message-ID: <a8cr5m$rar9j$1@ID-125440.news.dfncis.de>
In article <···················@Tron.ddeus.lan>, Oleksandr Kozachuk wrote:
> Hi all!
> 
> I need help with slots.
> 
> (defclass test () ((v1 :accessor test-v1)))
> 
> Now this work correct:
> 
> (setq a (make-instance 'test))
> (setf (test-v1 a) 2)
> (test-v1 a)
> 
>=> 2

That's one of the things specifying an ``:accessor'' does: It
automatically defines a (setf test-v1) method.  If you want
to provide your own, maybe you should rather specify a :reader
only and define the (setf test-v1) method seperately.

> But on "setf" it must call a funktion, but this _DONT WORK_:
> 
> (defclass test () ((v1 :accessor test-v1 :writer test-v1-set)))

Now you have even two methods for setting v1:

(setf (test-v1 a) 2)

or

(test-v1-set 2 a)

> (defmethod test-v1-set ((self test) (data number))
>     (setf (slot-value self 'v1) (+ data 1)))

And here you overwrite the test-v1-set method that had been
automatically defined just before :-)  Or rather: You don't overwrite
it, you have /yet another/ method, because you mixed up the order
of arguments.  Now,

(test-v1-set 2 a)

will still work, and so will

(test-v1-set a 2)

:-)  The latter will invoke your explicitly defined method,
the former will invoke the automatically defined writer method.

> (setq a (make-instance 'test))
> (setf (test-v1 a) 2)
> (test-v1 a)
> 
>=> 2 (why???)

Why not?  By specifying ``:accessor'', you had (setf test-v1)
automatically defined.

> How can i change the data?
> 
> Maybe anything like this (dont work):
> 
> (defmethod (setf test-v1) ((self test) (data number))
>     (setf (slot-value self 'v1) (+ data 1)))

Maybe like this:

CL-USER 1 > (defclass test ()
              ((v1 :reader test-v1)))
#<STANDARD-CLASS TEST 206675CC>

CL-USER 2 > (defmethod (setf test-v1) ((data number) (self test))
              (setf (slot-value self 'v1) (1+ data)))
#<STANDARD-METHOD (SETF TEST-V1) NIL (NUMBER TEST) 20669B7C>

CL-USER 3 > (defparameter *test* (make-instance 'test))
*TEST*

CL-USER 4 > (setf (test-v1 *test*) 42)
43

CL-USER 5 > (test-v1 *test*)
43

CL-USER 6 > 

I hope I got everything right...

Regards,
-- 
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x42B32FC9
From: Oleksandr Kozachuk
Subject: Re: Slots
Date: 
Message-ID: <slrnaajs8a.8pt.Alex@Tron.ddeus.lan>
Thank you very match, i understand it now :-))

Alex.
From: Pierre R. Mai
Subject: Re: Slots
Date: 
Message-ID: <874riu2ce6.fsf@orion.bln.pmsf.de>
Oleksandr Kozachuk <····@DDeus.de> writes:

> But on "setf" it must call a funktion, but this _DONT WORK_:
> 
> (defclass test () ((v1 :accessor test-v1 :writer test-v1-set)))
> (defmethod test-v1-set ((self test) (data number))
>     (setf (slot-value self 'v1) (+ data 1)))
> 
> (setq a (make-instance 'test))
> (setf (test-v1 a) 2)
> (test-v1 a)
> 
> => 2 (why???)

Because you use (setf test-v1) to set the slot, yet your method is
defined on test-v1-set.  CLOS has no way of knowing that you want to
have the GF test-v1-set invoked.

> How can i change the data?
> 
> Maybe anything like this (dont work):
> 
> (defmethod (setf test-v1) ((self test) (data number))
>     (setf (slot-value self 'v1) (+ data 1)))

Elide the superfluous :writer slot-argument, and define:

(defmethod (setf test-v1) ((new-value number) (self test))
  (setf (slot-value self 'v1) (+ data 1)))

[ setf functions take the new value as their first argument, in order
  to allow &optional/&key/&rest arguments to work properly... ]

Now:

(setq a (make-instance 'test))
(setf (test-v1 a) 2)
(test-v1 a)

=> 3
(setf (test-v1 a) 'symbol)
(test-v1 a)

=> symbol

If that's what you want.  If you want to completely redefine the
behaviour of (setf test-v1), then either define a method that's only
specialized on test, and/or change the :accessor slot arg to a :reader
slot-arg, thus not generating the default method on (setf test-v1).

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein