From: Tamas K Papp on
Suppose I have a class

(defclass gamma ()
((alpha :accessor alpha :initarg :alpha)
(beta :accessor beta :initarg :beta)))

characterizing a gamma distribution. The (scaled) chi-square
distribution is actually a reparametrized gamma distribution, so I
thought of defining

(defmethod make-instance ((class (eql 'chi-square)) &key nu s)
(make-instance 'gamma :alpha (/ nu 2) :beta (* (/ nu 2) (expt s 2))))

This would come particularly handy, as in my code, I create
distributions using make-instance. Then I could do

(make-instance 'chi-square :nu 5 :s 2)

Is this allowed? Or is (eql (class-of (make-instance x ...)) x) an
invariant that has to be maintained? If so, is there a more
acceptable way of doing this? I am sure that the answer is in the HS
somewhere, but I could not find it.

Thanks,

Tamas
From: Pascal Costanza on
On 19/02/2010 11:35, Tamas K Papp wrote:
> Suppose I have a class
>
> (defclass gamma ()
> ((alpha :accessor alpha :initarg :alpha)
> (beta :accessor beta :initarg :beta)))
>
> characterizing a gamma distribution. The (scaled) chi-square
> distribution is actually a reparametrized gamma distribution, so I
> thought of defining
>
> (defmethod make-instance ((class (eql 'chi-square))&key nu s)
> (make-instance 'gamma :alpha (/ nu 2) :beta (* (/ nu 2) (expt s 2))))
>
> This would come particularly handy, as in my code, I create
> distributions using make-instance. Then I could do
>
> (make-instance 'chi-square :nu 5 :s 2)
>
> Is this allowed? Or is (eql (class-of (make-instance x ...)) x) an
> invariant that has to be maintained? If so, is there a more
> acceptable way of doing this? I am sure that the answer is in the HS
> somewhere, but I could not find it.

Section 11.1.2.1.2 of the HyperSpec states that the consequences are
undefined if you do, among other things, the following: "Defining a
method for a standardized generic function which is applicable when all
of the arguments are direct instances of standardized classes."

So let's cehck:

+ make-instance is indeed a standardized generic function.
+ 'chi-square is an instance of 'symbol, which is indeed a standardized
class.
+ So your method would indeed be applicable when all, here the only
argument is a direct instance of a standardized class.

So strictly speaking you're not allowed to do what you want.

HOWEVER: I think the restrictions with regard to eql specializers on
symbols are too strict here. The idea of these restrictions is to ensure
that different libraries do not clash with their own methods on
standardized generic functions, so this restriction ensures that your
methods are specialized one at least on of 'your own' entities. However,
with regard to eql specializers and symbols there is a very simple
criterion to claim that a symbol is 'your own' - that is exactly when
the symbol is interned in one of 'your own' packages. So if Common Lisp
finally gets a new revision, I would strongly suggest to relax this
restriction for eql specializers appropriately.

In the meantime there are two ways to deal with this:

+ You can either decide not to worry about this particular case and only
solve the issue in case a particular Common Lisp implementation
complains here. (I would actually expect most implementations to do what
you intend with your own method on make-instance.)

+ You can choose to define your own metaclass as a replacement, and then
define methods on make-instance that are applicable when the only
argument is a direct instance of your own metaclass (which is acceptable
according to that section in the HyperSpec).

By the way, it is the latter possibility that makes me assume that no
Common Lisp implementation would actually complain about eql
specializers on symbols here, because I find it hard to imagine an
optimization that works only for symbols, but leaves room for your own
metaclasses (as required by the CLOS MOP specification).



Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pillsy on
On Feb 19, 5:35 am, Tamas K Papp <tkp...(a)gmail.com> wrote:

> Suppose I have a class

> (defclass gamma ()
>   ((alpha :accessor alpha :initarg :alpha)
>    (beta :accessor beta :initarg :beta)))

> characterizing a gamma distribution.  The (scaled) chi-square
> distribution is actually a reparametrized gamma distribution, so I
> thought of defining

> (defmethod make-instance ((class (eql 'chi-square)) &key nu s)
>   (make-instance 'gamma :alpha (/ nu 2) :beta (* (/ nu 2) (expt s 2))))

> This would come particularly handy, as in my code, I create
> distributions using make-instance.

I'm going to do that annoying thing of suggesting that you solve your
problem in a different way instead of answering your question. If a
CHI-SQUARE distribution is-a GAMMA distribution, maybe you should just
use plain old inheritance here, and define an :AFTER method on
INITIALIZE-INSTANCE to set ALPHA and BETA?

Cheers,
Pillsy
From: Pascal J. Bourguignon on
Pascal Costanza <pc(a)p-cos.net> writes:

> On 19/02/2010 11:35, Tamas K Papp wrote:
>> Suppose I have a class
>>
>> (defclass gamma ()
>> ((alpha :accessor alpha :initarg :alpha)
>> (beta :accessor beta :initarg :beta)))
>>
>> characterizing a gamma distribution. The (scaled) chi-square
>> distribution is actually a reparametrized gamma distribution, so I
>> thought of defining
>>
>> (defmethod make-instance ((class (eql 'chi-square))&key nu s)
>> (make-instance 'gamma :alpha (/ nu 2) :beta (* (/ nu 2) (expt s 2))))
>>
>> This would come particularly handy, as in my code, I create
>> distributions using make-instance. Then I could do
>>
>> (make-instance 'chi-square :nu 5 :s 2)
>>
>> Is this allowed? Or is (eql (class-of (make-instance x ...)) x) an
>> invariant that has to be maintained? If so, is there a more
>> acceptable way of doing this? I am sure that the answer is in the HS
>> somewhere, but I could not find it.
>
> Section 11.1.2.1.2 of the HyperSpec states that the consequences are
> undefined if you do, among other things, the following: "Defining a
> method for a standardized generic function which is applicable when
> all of the arguments are direct instances of standardized classes."
>
> So let's cehck:
>
> + make-instance is indeed a standardized generic function.
> + 'chi-square is an instance of 'symbol, which is indeed a
> standardized class.
> + So your method would indeed be applicable when all, here the only
> argument is a direct instance of a standardized class.
>
> So strictly speaking you're not allowed to do what you want.
>
> HOWEVER: I think the restrictions with regard to eql specializers on
> symbols are too strict here. The idea of these restrictions is to
> ensure that different libraries do not clash with their own methods on
> standardized generic functions, so this restriction ensures that your
> methods are specialized one at least on of 'your own'
> entities. However, with regard to eql specializers and symbols there
> is a very simple criterion to claim that a symbol is 'your own' - that
> is exactly when the symbol is interned in one of 'your own'
> packages. So if Common Lisp finally gets a new revision, I would
> strongly suggest to relax this restriction for eql specializers
> appropriately.
>
> In the meantime there are two ways to deal with this:
>
> + You can either decide not to worry about this particular case and
> only solve the issue in case a particular Common Lisp implementation
> complains here. (I would actually expect most implementations to do
> what you intend with your own method on make-instance.)
>
> + You can choose to define your own metaclass as a replacement, and
> then define methods on make-instance that are applicable when the only
> argument is a direct instance of your own metaclass (which is
> acceptable according to that section in the HyperSpec).
>
> By the way, it is the latter possibility that makes me assume that no
> Common Lisp implementation would actually complain about eql
> specializers on symbols here, because I find it hard to imagine an
> optimization that works only for symbols, but leaves room for your own
> metaclasses (as required by the CLOS MOP specification).

We can also define a chi-square class with a specific
initialize-instance method,

or just a custom constructor (make-chi-square ...) and live
happily ever after.

--
__Pascal Bourguignon__