Statalist The Stata Listserver


[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

Re: st: creating an (external) global variable containing a structure


From   wgould@stata.com (William Gould, Stata)
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: creating an (external) global variable containing a structure
Date   Thu, 25 May 2006 15:14:03 -0500

Phil Schumm <pschumm@uchicago.edu> writes, 

> Suppose I want to create a global variable containing a structure  
> from within a function.  For example:
> 
>         struct mystruct {
>              real scalar    a
>         }
>         
>         void create_mystruct()
>         {
>              external struct mystruct scalar    foo
>         }
>
> I would have assumed that after calling create_mystruct(), foo would  
> contain a struct scalar, [...]

Of course Phil would think that; I'm sorry that it is not true.  In the case
of global structures, you must explicitly allocate them.  Phil figured that
out for himself.  He continues,

> This puzzled me, because it seems a bit inconsistent with the way  
> external declarations work for other types.  [...]
> the following will not compile:

>         void create_mystruct()
>         {
>              external struct mystruct scalar    foo
>              struct mystruct scalar             foobar
>
>              foobar = mystruct()
>              foo = &foobar  // this line yields a type mismatch error
>         }

No it will not, but Phil is almost there.  foo is a struct mystruct, 
not a pointer(struct mystruct). 

Change
               foo = &foobar  // this line yields a type mismatch error
to
               foo = foobar

and the code will work; watch:

        : struct mystruct {
        >         real scalar     a
        > }

        : 
        : void create_mystruct()
        > {
        >         external struct mystruct scalar foo
        >         struct mystruct scalar          foobar
        > 
        >         foobar = mystruct()
        >         foo = foobar
        > }

        : create_mystruct()

        : mata describe

              # bytes   type                        name and extent
        -------------------------------------------------------------------
                  148   void                        create_mystruct()
                   68   structdef scalar            mystruct()
                    8   struct scalar               foo
        -------------------------------------------------------------------

Of course, we could simplify the code to read, 

        void create_mystruct()
        {
                external struct mystruct scalar foo
        
                foo = mystruct()
        }

I know what's bothering Phil.  Along the way to the solution, Phil listed a 
structure.  Here's what happens if I list it right now:

	: foo
          0x84b47e0

It looks like a pointer.  In addition, note that -mata describe- reports 
the size of -foo- as being 8 bytes.  Make the structure bigger, and it will
still be 8 bytes.

So here's the secret:  Internally, inside Mata, all structures are pointers.
That fact is pretty well hidden unless you look at a structure naked, and you
can do that by using the default display of Mata.  If Phil is interested in
exploring this point of arcania, he sould type 

        . viewsource liststruct.mata

There he will discover that a structure is in fact a pointer(pointer
colvector).  The elements of the colvector point to the members.
-liststruct-, written in Mata, uses that fact to explore and to display
structures.

It is not necessary to understand the insides of Mata in order to understand
structures, but Phil might be interested in doing so.  

What is important to understand is that globals must be allocated.  Actually,
I'm a little surprised (but only a little) that Phil's original attempt did
not work, namely

>         struct mystruct {
>              real scalar    a
>         }
>         
>         void create_mystruct()
>         {
>              external struct mystruct scalar    foo
>         }

It does not, however, and I want to look into that.  Maybe it can be fixed.
What is happening is that the external is being marked as a pointer rather 
than structure.  

In the meantime, coding

        void create_mystruct()
        {
                external struct mystruct scalar foo
        
                foo = mystruct()
        }

will work, and will always work.

-- Bill
wgould@stata.com
*
*   For searches and help try:
*   http://www.stata.com/support/faqs/res/findit.html
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/



© Copyright 1996–2014 StataCorp LP   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index