Note: This FAQ is based on a question and answer that appeared on
Statalist.
How do I
signal the alternative types of arguments to program options?
| Title |
|
Syntax for allowing alternative types of arguments to program options |
| Authors |
Nicholas Winter, Cornell University
Michael Blasnik, Blasnik & Associates
Nicholas J. Cox, Durham University, UK |
| Date |
August 2002; minor revisions August 2005 |
Question:
I want to use syntax with an option, call it x1(), which
will be allowed to be either a real number or a numeric variable. Is
there an easy way to do this?
Answer:
Concretely, these two forms should be combined into one:
syntax, x1(real)
syntax, x1(varname numeric)
The short answer is that there are several ways to do it. Below, we outline
and exemplify three solutions. For background, see help
syntax,
capture, and
confirm or [P]
syntax, [P] capture, and [P] confirm.
Solution 1: Specify a string argument and examine its contents afterwards
Get x1() as a string, and then test it after your syntax line:
syntax , x1(string)
capture confirm variable `x1'
if _rc {
capture confirm number `x1'
if _rc {
di as error "x1() must be a new variable name or a number"
error 198
}
else local isvar 0
}
else local isvar 1
This also sets the local macro isvar to indicate if x1()
specified a variable name or a number in case you need to take different
action for each.
If the syntax included other elements, they can be included in the
syntax statement as usual.
Solution 2: Use two alternative syntaxes together with capture
capture syntax , x1(real)
if _rc capture syntax, x1(varname numeric)
else local isvar 0
if _rc {
di as err "x1() must be a new variable name or a number"
exit 198
}
else local isvar 1
That is, if one syntax does not fit, the other one must.
This also sets the local macro isvar to indicate if x1()
specified a variable name or a number in case you need to take different
action for each.
If the syntax included other elements,
capture syntax ... , x1(real) ...
if _rc {
syntax ... , x1(varname numeric) ...
local isvar 1
}
else local isvar 0
If the problem is with what was in x1(), then the user will get a
message to that effect. If the problem lies with other stuff, then there
will be a message to that effect. The only loss is a little informativeness.
Solution 3: Use two options with the same abbreviation
To get two types of behavior from the same option, type
syntax [, X1a(real 0) X1b(varname numeric)]
local nopts = (`x1a' != 0) + ("`x1b'" != "")
if `nopts' == 0 {
di as err "x1() option required"
exit 198
}
else {
local isvar = "`x1b'" != ""
local x1 = cond(`isvar', "`x1b'", "`x1a')
}
This also sets the local macro isvar to indicate if x1()
specified a variable name or a number in case you need to take different
action for each.
The online help should just list a single option named x1(), flagging
the fact that different types of arguments are acceptable. Here, you are
exploiting that Stata allows option names to have the same
abbreviation, as long as the full option name differs. syntax will
then parse what the user types as you wish.
Note that since x1a() is not a required option, it will return a
default value (0 in the example). In some problems, only certain values
make sense (say, positive values). Setting a default value that makes no
sense allows you to distinguish between what the user typed and the default.
Trickier circumstances can be dealt with by specifying that x1a()
takes a numlist with particular properties.
Alternatively, if there is a natural default number for x1() (again,
for example, 0), then the code can be based on
syntax [, X1a(real 0) X1b(varname numeric)]
local isvar = "`x1b'" != ""
local x1 = cond(`isvar', "`x1b'", "`x1a')
However, as above, because two options are allowed, it is possible that a
user might specify both of them, presumably by accident, and careful code
will trap this.
If the syntax includes other elements, they can be included in the
syntax statement as usual.
Note: The order of the authors’ names was determined by a
random shuffle in Stata of their surnames from alphabetical order after
set seed 123456789.
|