Statalist


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

Re: st: Automatically generating variable names in mata


From   wgould@stata.com (William Gould, StataCorp LP)
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: Automatically generating variable names in mata
Date   Sun, 26 Apr 2009 10:00:32 -0500

L B <luli.econ@gmail.com> writes, 

> I want to do something that will create all the mata variables using a
> list of which locals to bring into mata, and also to dynamically
> create the variable names to match the local names, i.e. I want to
> create a mata variable called "hairchar" with the contents of the
> local "hairchar". 

LB offerred the following code, but admitted it did not work:

        local characteristics hairchar weightchar heightchar ...

        mata:
            charvector=tokens(st_local(characteristics))

            for (i=1; 1=cols(charvector), i++) {
                `charvector[i]' = st_local(charvector[i])
            }
        end

I wrote an article for the Stata Journal on the use of macros in Mata
explaining what works and what doesn't work.  The above is firmly in the
doesn't-work category.  The short explanation is that Mata is a fully compiled
language and the compilation is made before the program is run, so any use of
macros that changes meaning at the time of execution is not going to work.
The article does a better job of explaining.  Anyone who's interested can get
the article at

        http://www.stata-journal.com/article.html?article=pr0040

although it will cost $7.

Here's what will work:

        local characteristics hairchar weightchar heightchar ...

        mata:
            charvector=tokens(st_local(characteristics))

            for (i=1; i<=cols(charvector); i++) {
                p  = crexternal(charvector[i])
                *p = st_local(charvector[i])
            }
        end

The above hinges on the use of pointers and before I launch into an
explanation, I warm you that pointers are the solution to few problems.  They
are, however, the solution to this one.

Function -crexternal("<name>") creates a Mata (global) variable named <name>,
which is easy enough to understand, and it returns a pointer to the created 
variable.  The issue is just creating the variable is not enough because you 
are going to want to fill it in.  In Stata, you would use macros to hold the
varying name just as LB did in his attempt.  In compiled languages, macros 
are no good for that, so -crexternal()- returns the address in memory of the
variable created.  Variables containing addresses are called pointers.  -p-
above is a pointer.  It conains something like 0x9601bc, which is a base-16
representation of an address in memory.

*p is not multiplication.  *p is the way one refers to the contents of an 
address.  If I were to code p = ..., that means to fill in p with ...
When I code *p = ..., that means to fill in the variable pointed to p or, 
if you prefer, the variable whose address is p.  Programmer jargon for this is
indirection.

Anyway, once this difficult-to-explain code has executed, LB will have 
exactly what he wants. 

-- Bill
wgould@stata.com
*
*   For searches and help try:
*   http://www.stata.com/help.cgi?search
*   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