📄 m1_ado.hlp
字号:
the arguments were nothing more than strings, and those strings were
passed to {cmd:calcsum()}.
{pstd}
Macro substitution is the most common way values are passed to
Mata subroutines. If we had a Mata function {cmd:add(}{it:a}{cmd:,}
{it:b}{cmd:)}, which could add numbers, we might code in our ado-file
{cmd:mata: add(`x', `y')}
{pstd}
and, if macro {cmd:`x'} contained 2 and macro {cmd:`y'} contained 3,
Mata would see
{cmd:mata: add(2, 3)}
{pstd}
and values 2 and 3 would be passed to the subroutine.
{pstd}
When you think about writing your Mata subroutine, the arguments your
ado-file will find convenient to pass and Mata will make convenient to use,
are
{phang2}
1. Numbers, which Mata calls real scalars, such as 2 and 3
({cmd:`x'} and {cmd:`y'}).
{phang2}
2. Names of variables, macros, scalars, matrices, etc.,
which Mata calls string scalars,
such as {cmd:"mpg"} and {cmd:"__0001dc"} ({cmd:"`varlist'"} and
{cmd:"`touse'"}),
{pstd}
To receive arguments of type (1), you code {cmd:real scalar} as
the type of the argument in the function declaration, and then use the
real scalar variable in your Mata code.
{pstd}
To receive arguments of type (2), you code {cmd:string scalar} as the
type of the argument in the function declaration, and then you use
one of the
{bf:{help m4_stata:[M-4] Stata interface functions}}
to go from the name to the contents.
If you receive a variable name, you will especially want to read about
the functions
{bf:{help mf_st_data:[M-5] st_data()}}
and
{bf:{help mf_st_view:[M-5] st_view()}}, although there are many other utilities
for dealing with variable names.
If you are dealing with local or global macros, scalars, or matrices,
you will want to see
{bf:{help mf_st_local:[M-5] st_local()}},
{bf:{help mf_st_global:[M-5] st_global()}},
{bf:{help mf_st_numscalar:[M-5] st_numscalar()}},
and
{bf:{help mf_st_matrix:[M-5] st_matrix()}}.
{title:Returning results to ado-code}
{pstd}
You have a lot more choices on how to return results from your Mata function
to the calling ado-code.
{phang2}
1. You can return results in {cmd:r()} -- as we did in our example --
or in {cmd:e()} or in {cmd:s()}.
{phang2}
2. You can return results in macros, scalars, matrices, etc.,
whose names are passed to your Mata subroutine as arguments.
{phang2}
3. You can highhandedly reach back into the calling ado-file and
return results in macros, scalars, matrices, etc., whose names are
of your devising.
{pstd}
In all cases, see {bf:{help mf_st_global:[M-5] st_global()}}.
{cmd:st_global()} is probably not the function you will use, but there
is a wonderfully useful table in the {it:Remarks} section that will
tell you exactly which function to use.
{pstd}
Also see all other
{bf:{help m4_stata:[M-4] Stata interface functions}}.
{pstd}
If you want to modify the Stata dataset in memory, see
{bf:{help mf_st_store:[M-5] st_store()}} and
{bf:{help mf_st_view:[M-5] st_view()}}.
{title:Advice: Use of matastrict}
{* index matastrict tt}{...}
{pstd}
The setting {cmd:matastrict}
determines whether declarations can be omitted
(see {bf:{help m2_declarations:[M-2] Declarations}}); by default,
you may. That is, {cmd:matastrict} is set {cmd:off}, but you can
turn it on by typing {cmd:mata} {cmd:set} {cmd:matastrict} {cmd:on};
see {bf:{help mata_set:[M-3] set}}.
Some users do, and some users do not.
{pstd}
So now, consider what happens when you include Mata source code directly in
the ado-file. When the ado-file is loaded, is {cmd:matastrict} set {cmd:on},
or is it set {cmd:off}? The answer is that it is {cmd:off}, because when you
include the Mata source code inside an ado-file, {cmd:matastrict} is
temporarily switched off when the ado-file is loaded even if the user running
the ado-file has previously set it on.
{pstd}
For example, varsum.ado could read
{hline 50} varsum.ado {hline 5}
{cmd}program varsum
version 9.0
syntax varname [if] [in]
marksample touse
mata: calcsum("`varlist'", "`touse'")
display as txt " sum = " as res r(sum)
end
version 9.0
mata:
void calcsum(varname, touse)
{c -(}{col 50}{txt:{it:(note absence of declarations)}}
st_view(x, ., varname, touse)
st_numscalar("r(sum)", colsum(x))
}
end{txt}
{hline 50} varsum.ado {hline 5}
{pstd}
and it will work even when run by users who have {cmd:set} {cmd:matastrict}
{cmd:on}.
{pstd}
Similarly, in an ado-file, you can {cmd:set} {cmd:matastrict} {cmd:on}
and that will not affect the setting after the ado-file is loaded, so
varsum.ado could read
{hline 50} varsum.ado {hline 5}
{cmd}program varsum
version 9.0
syntax varname [if] [in]
marksample touse
mata: calcsum("`varlist'", "`touse'")
display as txt " sum = " as res r(sum)
end
version 9.0
mata:
mata set matastrict on
void calcsum(string scalar varname, string scalar touse)
{
real colvector x
st_view(x, ., varname, touse)
st_numscalar("r(sum)", colsum(x))
}
end{txt}
{hline 50} varsum.ado {hline 5}
{pstd}
and not only will it work, but running {cmd:varsum} will not change the
user's {cmd:matastrict} setting.
{pstd}
This preserving and restoring of {cmd:matastrict} is something that is
done only for ado-files when they are loaded.
{title:Advice: Some useful Mata functions}
{pstd}
In the {cmd:calcsum()} subroutine, we used the {cmd:colsum()} function --
see {bf:{help mf_sum:[M-5] sum()}} -- to obtain the sum:
{cmd}void calcsum(string scalar varname, string scalar touse)
{
real colvector x
st_view(x, ., varname, touse)
st_numscalar("r(sum)", colsum(x))
}{txt}
{pstd}
Alternatively, we could have coded,
{cmd}void calcsum(string scalar varname, string scalar touse)
{
real colvector x
real scalar i, sum
st_view(x, ., varname, touse)
sum = 0
for (i=1; i<=rows(x); i++) sum = sum + x[i]
st_numscalar("r(sum)", sum)
}{txt}
{pstd}
The first way is preferred. Rather than construct explicit loops, it is
better to call functions that calculate the desired result when such functions
exist. Unlike ado-code, however, when such functions do not exist, you can
code explicit loops and still obtain good performance.
{pstd}
Another set of functions we recommend are
documented in
{bf:{help mf_cross:[M-5] cross()}},
{bf:{help mf_crossdev:[M-5] crossdev()}},
and
{bf:{help mf_quadcross:[M-5] quadcross()}}.
{pstd}
{cmd:cross()} makes calculations of the form
{it:X}'{it:X}
{it:X}'{it:Z}
{it:X}{cmd:'diag(}{it:w}{cmd:)}{it:X}
{it:X}{cmd:'diag(}{it:w}{cmd:)}{it:Z}
{pstd}
{cmd:crossdev()} makes calculations of the form
({it:X}:-{it:x})'({it:X}:-{it:x})
({it:X}:-{it:x})'({it:Z}:-{it:z})
({it:X}:-{it:x})'{cmd:diag(}{it:w})({it:X}:-{it:x})
({it:X}:-{it:x})'{cmd:diag(}{it:w})({it:Z}:-{it:z})
{pstd}
Both these functions could easily escape your attention because the
matrix expressions themselves are so easily written in Mata.
The functions, however, are quicker, use less
memory, and, in some cases, are more accurate.
In addition, quad-precision versions of the functions exist;
{bf:{help mf_quadcross:[M-5] quadcross()}}.
{title:Also see}
{psee}
Manual: {bf:[M-1] ado}
{psee}
Online:
{bf:{help m2_version:[M-2] version}};
{bf:{help mata:[M-0] intro}},
{bf:{help m1_intro:[M-1] intro}}
{p_end}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -