Referencing Macro Variables Indirectly

Introduction

In the last example, you saw how to use the SYMPUT routine to create a series of macro variables whose names are based on the values of Course_code. However, you still needed to modify the TITLE statement in each PROC PRINT step in order to print output for each course.
Suppose you want to write a PROC PRINT step that you can reuse without any modification to print information about each course. You can do this by using an indirect reference in the TITLE statement.
data _null_;
   set sasuser.courses;
   call symput(course_code,trim(course_title));
run;

%let crsid=C002;
proc print data=sasuser.schedule noobs label;
   where course_code="&crsid";
   var location begin_date teacher;
   title1 "Schedule for ???";
run;
In the example above, the macro variable C002 (as created by the SYMPUT routine) has a value of Structured Query Language. Therefore, the TITLE statement should reference a macro variable that resolves to Structured Query Language. Remember that you want this reference to be flexible enough to apply to any of the macro variables that the SYMPUT routine creates, such as C003 or C004, by changing only the %LET statement.
To obtain the value Structured Query Language, you need to indirectly reference the macro variable C002 through a reference to the macro variable crsid. If the value of the macro variable crsid is C002, then you need to proceed in several steps:
  1. Resolve the macro variable crsid to the value C002.
  2. Attach an ampersand (&) to the front of the resolved value in order to create a new reference (&C002).
  3. Resolve the resulting macro variable reference to the value Structured Query Language.
This sequence seems to imply that you should use the reference &&crsid to convert the value of the macro variable crsid to the corresponding course description. However, the Forward Re-Scan rule indicates that this is not the correct solution.

The Forward Re-Scan Rule

The Forward Re-Scan rule can be summarized as follows:
  • When multiple ampersands or percent signs precede a name token, the macro processor resolves two ampersands (&&) to one ampersand (&), and re-scans the reference.
  • To re-scan a reference, the macro processor scans and resolves tokens from left to right from the point where multiple ampersands or percent signs are coded, until no more triggers can be resolved.
According to the Forward Re-Scan rule, you need to use three ampersands in front of a macro variable name when its value matches the name of a second macro variable. This indirect reference resolves to the value of the second macro variable.

Example

Suppose you want to use the macro variable crsid to indirectly reference the macro variable C002.
Global Symbol Table
The following table shows several references along with their resolved values.
References with resolved values
By preceding a macro variable reference with two ampersands, you delay the resolution of the reference until the second scan. The first time the reference is scanned, only the double ampersands are resolved (to one ampersand). In order to create an indirect reference (a reference whose value is a reference to a different macro variable), you must use three ampersands. Therefore, to use an indirect reference that resolves to Structured Query Language, the original reference must be &&&crsid.

Example

You can use indirect referencing to improve the last example. By using an indirect reference to the macro variable whose name is the same as the current value of the macro variable crsid, you can write a PROC PRINT step that you can reuse without modification in order to print a report for each different course.
options symbolgen;
data _null_;
   set sasuser.courses;
   call symput(course_code, trim(course_title));
run;
    
%let crsid=C005;
proc print data=sasuser.schedule noobs label;
   where course_code="&crsid";
   var location begin_date teacher;
   title1 "Schedule for &&&crsid";
run;

%let crsid=C002;
proc print data=sasuser.schedule noobs label;
   where course_code="&crsid";
   var location begin_date teacher;
   title1 "Schedule for &&&crsid";
run;
The SAS log shows the steps that lead to the resolution of these macro variables for each PROC PRINT step.
Table 10.5 SAS Log
43   options symbolgen;
44   data _null_;
45      set sasuser.courses;
46      call symput(course_code, trim(course_title));
47   run;
NOTE: There were 6 observations read from the dataset
      SASUSER.COURSES.
NOTE: DATA statement used:
      real time           0.07 seconds
      cpu time            0.05 seconds

48
49   %let crsid=C005;
50   proc print data=sasuser.schedule noobs label;
51      where course_code="&crsid";
SYMBOLGEN: Macro variable CRSID resolves to C005
52      var location begin_date teacher;
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable CRSID resolves to C005
SYMBOLGEN:  Macro variable C005 resolves to Artificial
            Intelligence
53      title1 "Schedule for &&&crsid";
54   run;

NOTE: There were 3 observations read from the dataset
      SASUSER.SCHEDULE.
      WHERE course_code='C005';
NOTE: PROCEDURE PRINT used:
      real time           0.09 seconds
      cpu time            0.04 seconds

55
56   %let crsid=C002;
57   proc print data=sasuser.schedule noobs label;
58      where course_code="&crsid";

SYMBOLGEN:  Macro variable CRSID resolves to C002
59      var location begin_date teacher;
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable CRSID resolves to C002
SYMBOLGEN:  Macro variable C002 resolves to Structured
            Query Language
60      title1 "Schedule for &&&crsid";
61   run;

NOTE: There were 3 observations read from the dataset
      SASUSER.SCHEDULE.
      WHERE course_code='C002';
NOTE: PROCEDURE PRINT used:
      real time           0.06 seconds
      cpu time            0.04 seconds
This is the output from the first PROC PRINT step.
Schedule for artificial intelligence
This is the output from the second PROC PRINT step.
Schedule for structured query language
Note that the PROC PRINT steps that produced these reports were identical. Only the %LET statement that precedes each PROC PRINT step and the resolved values of the macro variables changed.
Indirect referencing is especially useful when you are working with a series of related macro variables. In Introducing Macro Variables, you learned how to combine multiple macro variable references in order to build new tokens. You can combine indirect macro variable references with other macro variable references as well. That is, you can use two ampersands in a reference when the value of one macro variable matches part of the name of a second macro variable.

Example

You can create a series of macro variables, teach1 to teachn, each containing the name of the instructor who is assigned to a specific course.
options symbolgen;
data _null_;
   set sasuser.schedule;
   call symput('teach'||left(course_number),
               trim(teacher));
run;
Note: The concatenation operator || combines text. In the example above, the literal string teach is concatenated to the text that results from left-aligning the resolved value of the variable Course_number.
Global symbol table
Then, you can reference one of these variables when a course number is designated. If you designate a course number in a %LET statement, you can use multiple ampersands in order to create a reference to the teachn macro variable that corresponds to the current course number.
%let crs=3;
proc print data=sasuser.register noobs;
   where course_number=&crs;
   var student_name paid;
   title1 "Roster for Course &crs";
   title2 "Taught by &&teach&crs";
run;
The SAS log shows the steps that lead to the resolution of the reference &&teach&crs.
Table 10.6 SAS LOG
65   %let crs=3;
66   proc print data=sasuser.register noobs;
67      where course_number=&crs;
SYMBOLGEN:   Macro variable CRS resolves to 3
68      var student_name paid;
SYMBOLGEN:   Macro variable CRS resolves to 3
69     title1 "Roster for Course &crs";
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable CRS resolves to 3
SYMBOLGEN:  Macro variable TEACH3 resolves to
            Forest, Mr. Peter
70     title2 "Taught by &&teach&crs";
71   run;
This is the output from the example.
Roster for course 3 taught by Forest, Mr. Peter
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.178.53