"Sputnik" help  
Sputnik Help
Language Reference - Preprocessor - Macro Arguments

Macro Arguments

Function-like macros can take arguments, just like true functions. To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid Sputnik identifiers, separated by commas and optionally whitespace.

To invoke a macro that takes arguments, you write the name of the macro followed by a list of actual arguments in parentheses, separated by commas. The invocation of the macro need not be restricted to a single logical line—it can cross as many lines in the source file
as you wish.

The number of arguments you give must match the number of parameters in the macro definition. When the macro is expanded, each use of a parameter in its body is replaced by the tokens of the corresponding argument. (You need not use all of the parameters in the macro body.)

As an example, here is two macros that computes the minimum/maximum of two numeric values, as it is defined in many C programs, and some uses.

#define MAX(x, y) ((x) < (y) ? (y) : (x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
my $a = 10;
my $b = 20;
my $c = 27;
my $x = MIN($a, $b); // my $x = (($a) < ($b) ? ($a) : ($b));
my $y = MAX(1, 2); // my $y = ((1) < (2) ? (2) : (1));
my $z = MIN(1 + 28, $c); // my $z = ((1 + 28) < ($c) ? (1 + 28) : ($c));
say $x;
say $y;
say $z;
// 10
// 2
// 27

(In this small example you can already see several of the dangers of macro arguments. See Macro Pitfalls, for detailed explanations.)

Leading and trailing whitespace in each argument is dropped, and all whitespace between the tokens of an argument is reduced to a single space. Parentheses within each argument must balance; a comma within such parentheses does not end the argument. However,
there is no requirement for square brackets or braces to balance, and they do not prevent a comma from separating arguments. Thus you must use ( ) parentheses only.

All arguments to a macro are completely macro-expanded before they are substituted into the macro body. After substitution, the complete text is scanned again for macros to expand, including the arguments. This rule may seem strange, but it is carefully designed
so you need not worry about whether any function call is actually a macro invocation. You can run into trouble if you try to be too clever, though. See Argument Prescan, for detailed discussion.

For example

#define MIN(x, y) ((x) < (y) ? (x) : (y))
my $a = 10;
my $b = 20;
my $c = 5;
say MIN(MIN($a, $b), $c);
// 5

Is first expanded to

say ((($a) < ($b) ? ($a) : ($b)), ($c));

and then to

say (((($a) < ($b) ? ($a) : ($b))) < ($c)
    ? ((($a) < ($b) ? ($a) : ($b)))
    : ($c));

(Line breaks shown here for clarity would not actually be generated.)

You can leave macro arguments empty; this is not an error to the preprocessor (but many macros will then expand to invalid code). You cannot leave out arguments entirely; if a macro takes two arguments, there must be exactly one comma at the top level of its
argument list. Here are some silly examples using MIN:

MIN(, $b); // (( ) < (b) ? ( ) : (b))
MIN($a, ); // ((a ) < ( ) ? (a ) : ( ))
MIN(,); // (( ) < ( ) ? ( ) : ( ))
MIN((,),); // (((,)) < ( ) ? ((,)) : ( ))
// All Errors

Whitespace is not a preprocessing token, so if a macro FOO takes one argument, FOO() and FOO( ) both supply it an empty argument.

You can also place macros inside Strings like so

#define MIN(x, y) ((x) < (y) ? (x) : (y))
say "Value is {MIN(10, 20)}";
// Value is 10

Macro parameters appearing inside string literals are not replaced by their corresponding actual arguments.

#define FOO(x) say (x, "x");
FOO(10) // say(10, "x")
// 10
// x

See Stringification to learn more.

Be sure to check out Default Arguments to learn about how to create optional arguments for your macros.

Cheryl (uberfox@hotmail.com)