From: David Bakhash
Subject: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <wkyan12013.fsf@mit.edu>
This is a question that pertains to storage in classes, and to
`make-instance'.

Suppose I have a class with 3 "slots" (conceptually), but where knowing
only two yeilds the third. (for the sake of the question, let's call the
slots {A,B,C}.  So you don't want to store all three, because that's
redundant.  It's easy enough to just write a constructor that lets you
enter in the arguments (say) as keyword args, and then figures out how
to make and initialize the instance.  But, if you want to use
`make-instance'.  I'd like my `make-instance' to take the initargs and
then either fill or _compute_ the slot-values that are appropriate.  Is
this possible?

dave

From: Rainer Joswig
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <joswig-1701992230370001@194.163.195.67>
In article <··············@mit.edu>, David Bakhash <·····@mit.edu> wrote:

> This is a question that pertains to storage in classes, and to
> `make-instance'.
> 
> Suppose I have a class with 3 "slots" (conceptually), but where knowing
> only two yeilds the third. (for the sake of the question, let's call the
> slots {A,B,C}.  So you don't want to store all three, because that's
> redundant.  It's easy enough to just write a constructor that lets you
> enter in the arguments (say) as keyword args, and then figures out how
> to make and initialize the instance.  But, if you want to use
> `make-instance'.  I'd like my `make-instance' to take the initargs and
> then either fill or _compute_ the slot-values that are appropriate.  Is
> this possible?
> 
> dave

(defclass test ()
   ((bar :initarg :bar)
    (baz :initarg :baz)))

(defmethod initialize-instance :after ((object test) &rest initargs &key foo)
  ; do something
  )

(make-instance 'test
  :bar 1
  :baz 2
  :foo 3)

-- 
http://www.lavielle.com/~joswig
From: Lyman S. Taylor
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <77u8tp$rgi@pravda.cc.gatech.edu>
In article <·······················@194.163.195.67>,
Rainer Joswig <······@lavielle.com> wrote:
>In article <··············@mit.edu>, David Bakhash <·····@mit.edu> wrote:
...
>> Suppose I have a class with 3 "slots" (conceptually), but where knowing
>> only two yeilds the third. (for the sake of the question, let's call the
>> slots {A,B,C}.  So you don't want to store all three, because that's
>> redundant.
....
>> `make-instance'.  I'd like my `make-instance' to take the initargs and
>> then either fill or _compute_ the slot-values that are appropriate.  Is
>> this possible?

    If there is indeed a mapping be two to yield a third you may wish
    to "check" when all three are passed to make sure it is consistant.
    Otherwise, I may not be such a good design choice to allow this 
    virtual/computed slot to be specified. 

    Additionally, in the in the case the third is "computed" you may wish
    to make the other two slots required (must be initialized). Then the 
    accessor for the virtual/compued slot can always be computed upon
    demand.  Again foregoing the need to for additional checks. 
    

>(defmethod initialize-instance :after ((object test) &rest initargs &key foo)
>  ; do something
>  )


-- 
					
Lyman S. Taylor          "The Borg --  party poopers of the Galaxy. "
(·····@cc.gatech.edu)                 EMH Doctor  Star Trek Voyager. 
From: Thomas A. Russ
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <ymisod5wis9.fsf@sevak.isi.edu>
·····@cc.gatech.edu (Lyman S. Taylor) writes:

> 
> 
>     If there is indeed a mapping be two to yield a third you may wish
>     to "check" when all three are passed to make sure it is consistant.
>     Otherwise, I may not be such a good design choice to allow this 
>     virtual/computed slot to be specified. 

A good point.

>     Additionally, in the in the case the third is "computed" you may wish
>     to make the other two slots required (must be initialized). Then the 
>     accessor for the virtual/compued slot can always be computed upon
>     demand.  Again foregoing the need to for additional checks. 

I think the problem statement was more general than this.  Given any two
out of the three initializers, the third could be computed.  This is not
uncommon in some sorts of constraint systems.  For example, if one had a
class that represented a binary addition constraint, then you could have
something like:

  (defclass addition-constraint
   ((a :initarg :a)
    (b :initarg :b)
    (sum :initarg :sum)))

Any of the following would be reasonable initializations of this
constraint argument:

  (make-instance 'addition-constraint :a 1 :b 2)    ;  sum = 3
  (make-instance 'addition-constraint :a 1 :sum 5)  ;  b = 4
  (make-instance 'addition-constraint :b 2 :sum 9)  ;  a = 7
  (make-instance 'addition-constraint :a 2 :b 2 :sum 4)

but as you point out above, one would need to guard against:

  (make-instance 'addition-constraint :a 2 :b 2 :sum 5)  ; !!!



-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Kenny Tilton
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <36A2B6D1.DCFBC06@liii.com>
David Bakhash wrote:

> I'd like my `make-instance' to take the initargs and
> then either fill or _compute_ the slot-values that are appropriate.  Is
> this possible?

Would an #'initialize-instance after method do what you want?

ken
From: David Bakhash
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <wku2xo1phu.fsf@mit.edu>
Kenny Tilton <····@liii.com> writes:

> David Bakhash wrote:
> 
> > I'd like my `make-instance' to take the initargs and
> > then either fill or _compute_ the slot-values that are appropriate.  Is
> > this possible?

as someone else pointed out...probably.

thanks, all

dave
From: Lieven Marchand
Subject: Re: CLOS: initarg for a slot that's not there
Date: 
Message-ID: <782gte$7j1$1@nickel.uunet.be>
David Bakhash <·····@mit.edu> writes:

> This is a question that pertains to storage in classes, and to
> `make-instance'.
> 
> Suppose I have a class with 3 "slots" (conceptually), but where knowing
> only two yeilds the third. (for the sake of the question, let's call the
> slots {A,B,C}.  So you don't want to store all three, because that's
> redundant.  It's easy enough to just write a constructor that lets you
> enter in the arguments (say) as keyword args, and then figures out how
> to make and initialize the instance.  But, if you want to use
> `make-instance'.  I'd like my `make-instance' to take the initargs and
> then either fill or _compute_ the slot-values that are appropriate.  Is
> this possible?
> 
> dave

Use initialize-instance or shared-initialize. You'll find an example in Sonya 
Keene's book on CLOS on p.162. 

The following should give you an idea. 

USER(1): (defclass foo () (a b))
#<STANDARD-CLASS FOO>
; third slot c is the sum of a and b
USER(2): (defmethod c ((obj foo)) (+ (slot-value obj 'a) (slot-value obj 'b)))
#<STANDARD-METHOD C (FOO)>
; should add error checking that at least two key arguments are set and that
; when there are three given, they are consistent.
USER(4):
(defmethod initialize-instance :after ((obj foo) &key a b c)
  (when (and a b) (setf (slot-value obj 'a) a (slot-value obj 'b) b))
  (when (and a c) (setf (slot-value obj 'a) a (slot-value obj 'b) (- c a)))
  (when (and b c) (setf (slot-value obj 'b) b (slot-value obj 'a) (- c b))))
#<STANDARD-METHOD INITIALIZE-INSTANCE (FOO)>
USER(5): (make-instance 'foo :a 1 :b 2)
#<FOO @ #x835f97a>
USER(6): (c *)
3
USER(7): (make-instance 'foo :a 1 :c 3)
#<FOO @ #x835ff62>
USER(8): (slot-value * 'b)
2

-- 
Lieven Marchand <···@bewoner.dma.be> 
------------------------------------------------------------------------------
Few people have a talent for constructive laziness. -- Lazarus Long