Phil Schumm <[email protected]> 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
[email protected]
*
* 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/