📄 m2_declarations.hlp
字号:
There are six {it:eltypes}, or element types:
{p 8 12 2}
1. {cmd:transmorphic}, which means {cmd:real}, {cmd:complex},
{cmd:string}, or {cmd:pointer}.
{p 8 12 2}
2. {cmd:numeric}, which means {cmd:real} or {cmd:complex}.
{p 8 12 2}
3. {cmd:real}, which means that the elements are real numbers, such as 1,
3, -50, 3.14159, etc.
{p 8 12 2}
4. {cmd:complex}, which means that each element is a pair of numbers,
which are given the interpretation {it:a}+{it:b}i. Note that
{cmd:complex} is a storage type; the number stored in a {cmd:complex}
might be real, such as 2+0i.
{p 8 12 2}
5. {cmd:string}, which means the elements are strings of text. Each
element may contain up to 2,147,483,647 characters and strings
may (need not) contain binary 0, i.e., strings may be binary strings
or text strings.
{p 8 12 2}
6. {cmd:pointer} means the elements are pointers to (addresses of) other
Mata matrices, vectors, scalars, or even functions; see
{bf:{help m2_pointers:[M-2] pointers}}.
{title:Organizational types}
{p 4 4 2}
There are five {it:orgtypes}, or organizational types:
{p 8 12 2}
1. {cmd:matrix}, which means {it:r x c}, {it:r}>=0 and {it:c}>=0.
{p 8 12 2}
2. {cmd:vector}, which means 1 {it:x} {it:n} or {it:n} {it:x} 1,
{it:n}>=0.
{p 8 12 2}
3. {cmd:rowvector}, which means 1 {it:x} {it:n}, {it:n}>=0.
{p 8 12 2}
4. {cmd:colvector}, which means {it:n} {it:x} 1, {it:n}>=0.
{p 8 12 2}
5. {cmd:scalar}, which means 1 {it:x} 1.
{p 4 4 2}
Sharp-eyed readers will note that vectors and matrices can have zero rows
or columns! See {bf:{help m2_void:[M-2] void}} for more information.
{title:Function declarations}
{p 4 4 2}
Function declarations are the declarations that appear in front of the
function name, such as
{cmd:real matrix} swaprows(...)
{
...
}
{p 4 4 2}
The syntax for what may appear there is
{cmd:function}
{it:type} [{cmd:function}]
{cmd:void} [{cmd:function}]
{p 4 4 2}
Something must appear in front of the name, and if you do not want
to declare the type (which makes the type {cmd:transmorphic}
{cmd:matrix}), you just put the word {cmd:function}:
{cmd:function} swaprows(...)
{
...
}
{p 4 4 2}
Alternatively, you may declare the type and include the word {cmd:function}
if you wish,
{cmd:real matrix function} swaprows(...)
{
...
}
{p 4 4 2}
but most programmers omit the word {cmd:function}; it makes no difference.
{p 4 4 2}
In addition to all the usual types, {cmd:void} is a type allowed only with
functions -- it states that the function returns nothing:
{cmd:void} _swaprows(real matrix A, real scalar i1, real scalar i2)
{c -(}
real rowvector v
v = A[i1, .]
A[i1, .] = A[i2, .]
A[i2, .] = v
{c )-}{txt}
{p 4 4 2}
The function above returns nothing; it instead modifies the matrix it is
passed. That might be useful to save memory, especially if every use
of the original {cmd:swaprows()} was going to be
{cmd:A = swaprows(A, i1, i2)}
{p 4 4 2}
In any case, we named this new function {cmd:_swaprows()} (note the underscore),
to flag the user that there is something odd and deserving caution concerning
the use of this function.
{p 4 4 2}
{cmd:void}, that is to say, returning nothing, is also considered a special
case of a {cmd:transmorphic} {cmd:matrix} because Mata secretly returns a
0 {it:x} 0 real matrix, which the caller just discards.
{title:Argument declarations}
{p 4 4 2}
Argument declarations are the declarations that appear
inside the parentheses, such as
... swaprows({cmd:real matrix A, real scalar i1, real scalar i2})
{c -(}
...
{c )-}{txt}
{p 4 4 2}
The syntax for what may appear there is
[{it:type}] {it:argname} [{cmd:,} [{it:type}] {it:argname} [{cmd:,} ...]]
{p 4 4 2}
The names are required -- they specify how we will refer to the argument --
and the types are optional. Omit the type and {cmd:transmorphic} {cmd:matrix}
is assumed. Specify the type, and it will be checked when your function is
called. If the caller attempts to use your function incorrectly, Mata
will stop the execution and complain.
{title:The by-address calling convention}
{p 4 4 2}
Arguments are passed to functions by address, not by value. What that means
is that, if you change the value of an argument, you will change the caller's
argument. That is what made {cmd:_swaprows()} (above) work. The
caller passed us {cmd:A} and we changed it. And that is why in the original
version of {cmd:swaprows()}, the first line read
{cmd:B = A}
{p 4 4 2}
we did our work on {cmd:B}, and returned {cmd:B}. We did
not want to modify the caller's original matrix.
{p 4 4 2}
You do not ordinarily have to make copies of the caller's arguments, but you
do have to be careful if you do not want to change the argument. That is why
in all the official functions (with the single exception of
{bf:{help mf_st_view:st_view()}}), if a function changes the caller's
argument, the function's name starts with an underscore. The reverse logic
does not hold: some functions start with an underscore and do not change the
caller's argument. The underscore signifies caution, and you need to read the
function's documentation to find out what it is you need to be cautious about.
{title:Variable declarations}
{p 4 4 2}
The variable declarations are the declarations that appear at the
top of the body of a function:
... swaprows(...)
{
{cmd:real matrix B}
{cmd:real rowvector v}
...
}
{p 4 4 2}
These declarations are optional. If you omit them, Mata will observe
that you are using {cmd:B} and {cmd:v} in your code, and then Mata will
compile your code just as if you had declared the variables to be
{cmd:transmorphic} {cmd:matrix}, meaning the resulting compiled code
might be a little more inefficient than it could be, but that is all.
{* index matastrict tt}{...}
{p 4 4 2}
The variable declarations are optional as long as you have not {cmd:mata}
{cmd:set} {cmd:matastrict} {cmd:on}; see {bf:{help mata_set:[M-3] mata set}}.
Some programmers believe so strongly that variables really ought to be
declared that Mata provides a provision to issue an error when they forget.
{p 4 4 2}
In any case, these declarations -- explicit or implicit -- define
the variables we will use. The variables
we use in our function are private -- it does not matter if there are other
variables named {cmd:B} and {cmd:v} floating around somewhere. Private
variables are created when a function is invoked and destroyed when the
function ends. The variables are private but, as explained above, if we pass
our variables to another function, that function may change their values.
Most functions do not.
{p 4 4 2}
The syntax for declaring variables is
{it:type} {it:varname} [{cmd:,} {it:varname} [{cmd:,} ...]]
{cmd:external} [{it:type}] {it:varname} [{cmd:,} {it:varname} [{cmd:,} ...]]
{p 4 4 2}
{cmd:real matrix B} and {cmd:real rowvector v} match the first syntax.
{title:Linking to external globals}
{p 4 4 2}
The second syntax has to do with linking to global variables. When you
use Mata interactively and type
: {cmd:n = 2}
{p 4 4 2}
you create a variable named {cmd:n}. That variable is global. When you
code inside a function
... myfunction(...)
{
{cmd:external n}
...
}
{p 4 4 2}
The {cmd:n} variable your function will use is the global variable named
{cmd:n}. If your function were to examine the value of {cmd:n} right now, it
would discover that it contained 2.
{p 4 4 2}
If the variable does not already exist, the statement {cmd:external} {cmd:n}
will create it. Pretend we had not previously defined {cmd:n}. If
{cmd:myfunction()} were to examine the contents of {cmd:n}, it would discover
that {cmd:n} is a 0 {it:x} 0 matrix. That is because we coded
{cmd:external n}
{p 4 4 2}
and Mata behaved as if we had coded
{cmd:external transmorphic matrix n}
{p 4 4 2}
Let's modify {cmd:myfunction()} to read:
... myfunction(...)
{
{cmd:external real scalar n}
...
}
{p 4 4 2}
Let's consider the possibilities:
{p 8 12 2}
1. {cmd:n} does not exist.{break}
In this case, {cmd:external} {cmd:real} {cmd:scalar} {cmd:n} will
create {cmd:n} -- as a real scalar, of course -- and set its value
to missing.
{p 12 12 2}
If {cmd:n} had been declared a {cmd:rowvector}, a 1 {it:x} 0 vector
would have been created.
{p 12 12 2}
If {cmd:n} had been declared a {cmd:colvector}, a 0 {it:x} 1 vector
would have been created.
{p 12 12 2}
If {cmd:n} had been declared a {cmd:vector}, a 0 {it:x} 1 vector
would have been created. Mata could just as well have created
a 1 {it:x} 0 vector, but it creates a 0 {it:x} 1.
{p 12 12 2}
If {cmd:n} had been declared a {cmd:matrix}, a 0 {it:x} 0 matrix
would have been created.
{p 8 12 2}
2. {cmd:n} exists, and it is a {cmd:real scalar}.{break}
Our function executes, using the global {cmd:n}.
{p 8 12 2}
3. {cmd:n} exists, and it is a {cmd:real} 1 {it:x} 1
{cmd:rowvector}, {cmd:colvector}, or {cmd:matrix}.{break}
The important thing is that it is 1 {it:x} 1; our function executes,
using the global {cmd:n}.
{p 8 12 2}
4. {cmd:n} exists, but it is {cmd:complex} or {cmd:string} or
{cmd:pointer}, or it is {cmd:real} but not 1 {it:x} 1.{break}
Mata issues an error message and aborts execution of our function.
{p 4 4 2}
Complicated systems of programs sometimes find it convenient to
communicate via globals. Because globals are globals, we recommend
that you give your globals long names. A good approach is to put the name
of your system as a prefix:
... myfunction(...)
{
{cmd:external real scalar mysystem_n}
...
}
{p 4 4 2}
For another approach to globals, see
{bf:{help mf_findexternal:[M-5] findexternal()}}
and
{bf:{help mf_valofexternal:[M-5] valofexternal()}}.
{title:Also see}
{p 4 13 2}
Manual: {hi:[M-2] declarations}
{p 4 13 2}
Online: help for
{bf:{help m2_intro:[M-2] intro}}
{p_end}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -