14.2.4 Macro Arguments

This section explains how to use macro arguments. As an initial example, the following syntax defines a macro named !analyze that takes all the syntax up to the first command terminator as an argument:

DEFINE !analyze(!POSITIONAL !CMDEND)
DESCRIPTIVES !1.
FREQUENCIES /VARIABLES=!1.
!ENDDEFINE.

When !analyze is called, it expands to a pair of analysis commands with each !1 in the body replaced by the argument. That is, these calls:

!analyze v1 v2 v3.
!analyze v4 v5.

act like the following:

DESCRIPTIVES v1 v2 v3.
FREQUENCIES /VARIABLES=v1 v2 v3.
DESCRIPTIVES v4 v5.
FREQUENCIES /VARIABLES=v4 v5.

Macros may take any number of arguments, described within the parentheses in the DEFINE command. Arguments come in two varieties based on how their values are specified when the macro is called:

If a macro has both positional and keyword arguments, then the positional arguments must come first in the DEFINE command, and their values also come first in macro calls. A keyword argument may be omitted by leaving its keyword out of the call, and a positional argument may be omitted by putting a command terminator where it would appear. (The latter case also omits any following positional arguments and all keyword arguments, if there are any.) When an argument is omitted, a default value is used: either the value specified in !DEFAULT(value), or an empty value otherwise.

Each argument declaration specifies the form of its value:

!TOKENS(count)

Exactly count tokens, e.g. !TOKENS(1) for a single token. Each identifier, number, quoted string, operator, or punctuator is a token. See Tokens, for a complete definition.

The following variant of !analyze_kw accepts only a single variable name (or ALL) as its argument:

DEFINE !analyze_one_var(!POSITIONAL !TOKENS(1))
DESCRIPTIVES !1.
FREQUENCIES /VARIABLES=!1.
!ENDDEFINE.

!analyze_one_var v1.
!CHAREND('token')

Any number of tokens up to token, which should be an operator or punctuator token such as ‘/’ or ‘+’. The token does not become part of the value.

With the following variant of !analyze_kw, the variables must be following by ‘/’:

DEFINE !analyze_parens(vars=!CHARNED('/'))
DESCRIPTIVES !vars.
FREQUENCIES /VARIABLES=!vars.
!ENDDEFINE.

!analyze_parens vars=v1 v2 v3/.
!ENCLOSE('start','end')

Any number of tokens enclosed between start and end, which should each be operator or punctuator tokens. For example, use !ENCLOSE('(',')') for a value enclosed within parentheses. (Such a value could never have right parentheses inside it, even paired with left parentheses.) The start and end tokens are not part of the value.

With the following variant of !analyze_kw, the variables must be specified within parentheses:

DEFINE !analyze_parens(vars=!ENCLOSE('(',')'))
DESCRIPTIVES !vars.
FREQUENCIES /VARIABLES=!vars.
!ENDDEFINE.

!analyze_parens vars=(v1 v2 v3).
!CMDEND

Any number of tokens up to the end of the command. This should be used only for the last positional parameter, since it consumes all of the tokens in the command calling the macro.

The following variant of !analyze_kw takes all the variable names up to the end of the command as its argument:

DEFINE !analyze_kw(vars=!CMDEND)
DESCRIPTIVES !vars.
FREQUENCIES /VARIABLES=!vars.
!ENDDEFINE.

!analyze_kw vars=v1 v2 v3.

By default, when an argument’s value contains a macro call, the call is expanded each time the argument appears in the macro’s body. The !NOEXPAND keyword in an argument declaration suppresses this expansion. See Controlling Macro Expansion.