Bookmark and Share

Notice: On April 23, 2014, Statalist moved from an email list to a forum, based at statalist.org.


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: st: Re: reciprocal references between classes in Mata


From   Phil Schumm <[email protected]>
To   <[email protected]>
Subject   Re: st: Re: reciprocal references between classes in Mata
Date   Fri, 6 Sep 2013 21:19:35 -0500

On Sep 6, 2013, at 3:22 PM, [email protected] wrote:
> The trick here is to realize Mata does not require the class member function definition to immediately follow the class definition, you may delay the class member function definition as much as you want. The following code should do what Phil wants:
> 
> //-----------------------------------------------------------------------
> cscript
> mata:
> 
> mata clear	
> 
> class Results {
>    real scalar                         primary_outcome
>    pointer(class Study scalar) scalar  study
>    void                                myfunc()
> }
> 
> class Study {
>    string scalar                       type
>    class Results scalar                results
>    void                                new()
> }
> 
> void Results::myfunc() {
>    printf("The study type = %s\n", study->type)
> }
> 
> void Study::new() {
>    type = "RCT"
>    results = Results()
>    results.study = &this
> }
> 
> void testit() {
>    class Results scalar a
>    class Study scalar b
>    a.study = &b
>    a.myfunc() ;
> }
> 
> testit()	
> 
> end
> //-----------------------------------------------------------------------



Now that I've had a chance to look more closely at this, I have two follow-up comments.  First, the reordering of the method definition(s) suggested by Hua is, it seems, necessary in order to achieve the reciprocal references between classes that I was after.  In my case, both classes are large with a lot of method definitions, and so I have the source for each stored in a separate file.  Given this, it's a bit awkward to rearrange some of the methods for each class to follow the declaration of both classes, but this is not a big deal.

Second, note that what I had written originally has another problem; namely, I had wanted to establish the references between classes within the constructor for the Study class (e.g., the second two lines of Study::new()).  For example, consider the following modification of testit() above:


    void testit() {
        class Study scalar a
        class Results scalar b
        b = a.results
        b.study->type
        a.type = "Cohort"
        b.study->type
    }

    testit()	
    RCT
    RCT


This illustrates the fact that a and b.study are two separate objects, which hadn't occurred to me when I was fixated on the ordering issue.  Using references to "this" inside a constructor can be tricky, and I must confess I still don't have a solid grasp on why a and b.study are separate objects in Mata (e.g., is a copy of the Study instance returned following Study::new() rather than the instance itself?).  Nonetheless, I have for now resorted to a factory function that generates Studies, and within which I can establish the relevant references.  For some reason, however, this still doesn't feel very clean to me.  Perhaps it's because I spend so much time in Python where you can accomplish what I wrote originally with a reference to self within __init__() (of course in that case, __init__() really isn't a constructor).

Anyway, thanks again to Hua for the help.


-- Phil


*
*   For searches and help try:
*   http://www.stata.com/help.cgi?search
*   http://www.stata.com/support/faqs/resources/statalist-faq/
*   http://www.ats.ucla.edu/stat/stata/


© Copyright 1996–2018 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   Site index