2
votes

How can one define a macro variable containing references to other macro variables which have not yet been defined without generating a warning?


Consider a program which generates similar plots for different variables. Depending on the variable, the label of each figure will change. Since all the figures have the similar labels, except for the particular analysis variable, it makes sense to place the label at the top of the program for easy modification. The problem is, at that point in the program, the variable name has not been yet been defined.

For example:

/*Top of program*/
%let label = This &thing gets defined later.;

/* ... */

/*Later in program*/
%let thing = macro variable;
%put &=label;

This produces the desired output:

LABEL=This macro variable gets defined later.

But it also generates a warning in the log:

WARNING: Apparent symbolic reference THING not resolved.

If I put an %nrstr around &thing, then the form of label is correct (i.e . LABEL=This &thing gets defined later.) However, &thing no longer resolves after it has been defined.

/*Top of program*/
%let label = This %nrstr(&thing) gets defined later.;
%put &=label;

/* ... */

/*Later in program*/
%let thing = macro variable;
%put &=label;

This outputs:

LABEL=This &thing gets defined later.
LABEL=This &thing gets defined later.

Is there some way to avoid writing the warning to the log?

2

2 Answers

5
votes

Here is where understanding the difference between %STR type quoting and %QUOTE type quoting is helpful.

%QUOTE and its variants mask text when a macro executes, while %STR and its variants mask text when a macro compiles. In this case you're concerned with the latter, not the former, as you expect &thing to be resolved during execution - but not during compilation.

So it's %NRSTR to the rescue. You'll also need to use %UNQUOTE to get the macro variable to fully resolve - i.e., cancel out the NRSTR.

/*Top of program*/
%let label = This %nrstr(&thing.) gets defined later.;

/* ... */

/*Later in program*/
%let thing = macro variable;
%put %unquote(&label);
0
votes

Just use CALL SYMPUTX() in a data step to define the macro variable.

data _null_;
  call symputx('label','This &thing gets defined later.');
run;
/*Later in program*/
%let thing = macro variable;
%put &=label;