From: Tamas K Papp on 19 Feb 2010 05:35 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 19 Feb 2010 07:55 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 19 Feb 2010 09:44 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 19 Feb 2010 09:48 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__
|
Pages: 1 Prev: Lisp libraries Next: documentation generation libraries: which ones work? |