Statalist


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

st: RE: can one program a function in Stata?


From   "Nick Cox" <n.j.cox@durham.ac.uk>
To   <statalist@hsphsun2.harvard.edu>
Subject   st: RE: can one program a function in Stata?
Date   Thu, 23 Apr 2009 12:36:10 +0100

The short answer is No. 

That is, you cannot, as a user, write a Stata function so that it
behaves exactly like a StataCorp official function -- short of joining
StataCorp, becoming a developer, etc. -- meaning, write -foobar()- so
that you can put -foobar()- anywhere that an official function would be
legal. 

Martin and David gave less dogmatic answers with good advice, but more
can be said. Note that -egen- functions, whatever their merits, which I
have exploited myself, can't be used outside -egen- or to emit constants
as output (except inelegantly as variables full of the same constant). 

A Stata function is part of the executable. As Stata's executable code
is not open source, you can not see that or contribute to it. Even if
Stata were open source, to write a function, you would need to write
some C code, to know where to put it, and to re-compile the executable
to be able to do that. 

However, StataCorp could no doubt find a way to let you mimic that with
Stata code, so that you could e.g. put in a do file the definition of a
Stata function. It would require some low-level hits on Stata beyond
that facility, and I have no idea _exactly_ how difficult that would be.


I see this as a trade-off problem. Sometimes you want to write something
slightly complicated that just returns a constant. You can write a
program that leaves something in its wake or you can write a Mata
function which you call from Stata. The first can be a bit awkward,
undoubtedly, but the second is often more elegant. However, this kind of
need is quite rare. I estimate that less than 1% of my Stata programs
have the job of returning a constant (I am not counting programs that
act as subroutines). 

I have no idea whether StataCorp have seriously entertained introducing
the facility for users to define Stata functions, but my strong
impression is that there are plenty of more urgent tasks. 

If Stata were being rewritten from the ground up, and suggestions were
being solicited about design,  I'd suggest that users could define Stata
functions too, but it's not 1984 any more. 

I guess that Jacob's example was just a dopey one, but as Martin pointed
out you could use -cond(,)- to define that function. And that need not
be within a program: you could use it in-line to produce a constant. 

Nick 
n.j.cox@durham.ac.uk 

Martin Weiss
============

We can also get a grip on the problem using -cond()- so no heavy
machinery 
required...

clear
set obs 10

gen x=_n
gen myanswer=cond(x>3,(sqrt(x) + 5)^(2/3), (sqrt(x) + 9)^(2/3))

list, noobs

David Kantor
============ 

This gets asked fairly often. To my knowledge, there is no way to do 
what you asked for. (I don't know enough about mata to comment about
that.)

Stata doesn't let you do that, but you can have programs that deposit 
a value somewhere -- a variable, a scalar, an r() value (as you 
showed in your example), a global macro, a local macro (though there 
are issues about that, and it is discouraged). Despite this 
limitation, Stata users manage fairly well.

A notable example is -egen-, which is really a front end for a large 
suite of programs that deposit values into variables. -egen- is 
extensible; you can add your own programs to it. We often refer to 
these programs as "functions", though they really aren't functions. 
They just appear in a context and syntax that makes them look like 
functions. To see how to write an egen "function" see...
viewsource egen.ado
plus, look at one of the Stata-given programs, such as max (_gmax):
viewsource _gmax.ado

Martin Weiss
============

Just define your very own -egen- function, taking a cue from the
existing
ones (they all start with an _g, so they are easy to locate on the
ado-path). As it happens, Kit`s book has a section (3.4) on this
subject...

Jacob Wegelin
=============

I am about to order Kit Baum's Introduction to Stata Programming. But
I'm curious whether his book will answer the following question.

Stata has what I would call plain old functions, of which sqrt() is an
example:

. di sqrt(3.1415926535)
1.7724539

. sysuse auto, clear
(1978 Automobile Data)

. gen sqrtTurn=sqrt(turn)

But suppose I want to define a function that's not found under -help
functions-. The following approach (with a hypothetical nonstandard
function) seems clumsy:

capture program drop myownfunction
program define myownfunction, rclass
   if `1' > 3 {
      return scalar myanswer= (sqrt(`1') + 5)^(2/3)
      }
   else {
      return scalar myanswer= (sqrt(`1') + 9)^(2/3)
      }
end

myownfunction 3.1415926535
di r(myanswer)

Besides the awkward business of having to first call the function,
then refer to - r(myanswer) - , this program only works for a single
number (a scalar in the mathematical not Stata sense). If I want to
apply it to an entire column of numbers (a Stata numeric variable),
I'd have to write a different function, then always remember whether
to call the scalar or the vector (variable) version. On the other
hand, we can use sqrt() directly for either purpose.

Thus, is there a way to define -myownfunction()- so that one can call
it just as one calls sqrt()?  Does one do this with -mata-, or ...?
Would Kit Baum's book talk about this?


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