Stata The Stata listserver
[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

Re: st: [Mata] passing a function to mata (new question)


From   [email protected] (William Gould, Stata)
To   [email protected]
Subject   Re: st: [Mata] passing a function to mata (new question)
Date   Fri, 26 Aug 2005 08:47:43 -0500

Do you want to read this?
-------------------------

Mata is new and many of you have not tried it yet.  

I fear that if you read this question and answer, you will never use Mata.
You will come to the conclusion that Mata is suitable only for advanced 
programming problems and that using Mata requires knowledge that you do 
not have, nor much care to gain.

That would be unfortunate, because Mata really is easy to use and is worth
learning.  99.99% of all problems that will ever be approached using Mata will
not involve the topics discussed below.  Do not hold it against Mata that it
can deal with the 0.01% of problems, too.

All that said, what follows really is not difficult, it is merely unlikely 
that the majority of Statalisters would ever face the problem.


Question and response
---------------------

The subject is passing funtions to functions in Mata, and Ben Jann
<[email protected]> imagines a situation where the function he wants
to pass is given by a string variable:

        function me1(string scalar he)
        {
                      ...
                if (he=="he1")      y = me2(x, &he1())
                else if (he=="he2") y = me2(x, &he2())
                else if (he=="he3") y = me2(x, &he3())
                ...
                return(...)        
        }

Benn wonders if it is possible to code the above in such a way that the value
of string scalar he is used directly.  As Benn says,

> If Mata had macro expansion, I would type
>
>       function me1(string scalar he)
>       {
>              ...
>               y = me2(x, &`he'())
>               ...
>               return(...)        
>       }


Comment 1, "If Mata had macro expansion..."
-------------------------------------------

My recommendation is to stop thinking like that, although I know that 
after years of ado programming, that is difficult.

What makes Mata faster than ado?  It is the fact that Mata programs are
compiled, whereas ado programs are interpreted.  When you think in terms 
of macro expansion, you are thinking interpretive.

Mata in fact does have macro expansion but you have to distinguish between
expansion at compile time and expansion at run time.  The little bit of code
Benn produced would expand `he' at compile-time, and that is *NOT* what Benn
wants.

Expansion at run-time requires writing lots of code.  Don't go there.


Comment 2:  Can the string scalar be used directly?
---------------------------------------------------

No, not right now.  I have more to say on this, but let's go with the "No"
answer right now.

The most efficient thing to do is just what Benn said, 

        function me1(string scalar he)
        {
                      ...
                if (he=="he1")      y = me2(x, &he1())
                else if (he=="he2") y = me2(x, &he2())
                else if (he=="he3") y = me2(x, &he3())
                ...
                return(...)        
        }

Now imagine you had 15 places in your code where you wanted to execute 
function `he'() (excuse the macro notation).  You could do this:


        function me1(string scalar he)
        {
                ...
                if (he=="he1")      p = &he1()
                else if (he=="he2") p = &he2()
                else if (he=="he3") p = &he3()
                      ...
                      ...
                y = me2(x, p)                (1st call)
                ...
                y = me2(x, p)                (2nd call)
                ...
                ...
                y = me2(x, p)                (15th call)
}

In the above, p is a pointer.  If you felt like delcaring it, you
could delcare it

                pointer(function) p 

The point of the above is that something like &he1() is just an address,
and pointers hold addresses, and so you can use pointer variables to 
hold addresses of functions just as you can use them to hold addresses
of matrices, vectors, and scalars.


Comment 3:  Can the string scalar be used directly?
---------------------------------------------------

"No," I just said.

Have you seen the function [M-5] findexternal()?  Quoting from the
documentation,


    findexternal(name) returns a pointer to the external global 
    matrix, vector, or scalr whose name is specified by name; 
    it returns NULL if the external global is not found.


Thus, findexternal("x") returns the address of global x, if it exists.

findexternal("he1()") ought to return the address of function he1().
It does not, but it ought to, and I feel so strongly about that, I have 
just recorded it as a bug that it does not.

So let's imagine the "bug" is fixed.  Then Benn could code, 


        function me1(string scalar he)
        {
                      ...
                p = findexternal(he+"()")
                ...
                y = me2(x, p)
                ...
        }

Presumably, Benn ought to worry about p being NULL.

-- 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/



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