When we write a macro definition with parameters in SAS, we use these parameters when we call and execute them. Sometimes, we specify default values for keyword parameters and omit the explicit specification in the call. However, what if you want to write a macro with a variable number of arguments? We can do this with the Parmbuff Option. Macro programmers rarely use the Parmbuff option. However, it gives enormous flexibility. This post explores the Parmbuff Option by example.
The Parameter Buffer
First, let us take a look at the parameter buffer. The parameter buffer is a temporary storage location in memory. The SAS Parmbuff Option turns on the parameter buffer and lets the automatic macro variable &syspbuff hold the value in the buffer. Consider the code below. I write a simple macro %test and use the Parmbuff Option in the %Macro Statement. Then I print the content in the parameter buffer in the log. If you check the log you will see that SAS prints (abc). Including the parentheses. This is important to keep in mind.
%macro test / parmbuff; %put &syspbuff; %mend test; %doit(abc);
A Macro Function with Parmbuff
The Parmbuff Option lets programmers write macro definitions with a variable number of parameters. Let us consider a simple example of this. I want to write a macro function, that sums the input arguments. Regardless of the number of arguments. In the code below, I define the macro %sumthem. I do not specify any parameters in the %Macro Statement. Instead, I turn on the parameter buffer. Next, I initialize the macro variables i and s to 1 and 0 respectively. I use s to hold the sum to be returned and i to keep track of the number of parameters passed to the macro call.
I use a simple %Do %While Loop to loop over each parameter. This is done while the %Qscan Macro Function does not return a null value. The %str(,%(%)) part is used to mask commas, and opening/closing parenthesis. Remember, the &syspbuff variable includes the parentheses as well. Finally, I use the %Sysevalf Function to increment the sum and the %Eval Function to increment i by 1. I leave &s hanging without a semicolon to let this be the returned value of the macro function.
%macro sumthem / parmbuff; %local i j s; %let i = 1; %let s = 0; %do %while (%qscan(&syspbuff, &i, %str(,%(%))) ne %str()); %let j = %qscan(&syspbuff, &i, %str(,%(%))); %let s = %sysevalf(&s + &j); %let i = %eval(&i + 1); %end; &s %mend sumthem; %put The sum is %sumthem(1,2,3);
Run the code above and check the SAS log. The log prints the sum of 1, 2 and 3 which is 6. Verify that the macro works for different number of parameters.
A Classic Example from the Documentation
The documentation has a single example of using the parameter buffer. This is not a macro function, rather a regular macro. This means that it does not return a value. Rather, it simply generates code. The principle is similar to the one above. I use a %Do %While loop to loop over each input parameter. In this example though, no quoting is done. Though this works, I like the other approach better, because it ensures that no values are misinterpreted by the SAS macro processor.
%macro printz / parmbuff; %let num=1; %let dsname=%scan(&syspbuff,&num); %do %while(&dsname ne); proc print data=&dsname; run; %let num=%eval(&num+1); %let dsname=%scan(&syspbuff,&num); %end; %mend printz; %printz(purple,red,blue,teal)
In this post, we explore the Parmbuff Option in the SAS Macro Language. The Parmbuff Option enables us to write macro definitions with a variable number of parameters. This can come in handy in many different situations. Above, I provide a few examples. One of a macro function and one of a regular macro definition. The code can easily be modified to handle different situations as well.
If you want to learn more about the parameter buffer and the SAS Parmbuff Option, read This thread in the SAS Community and section 8.3.3 in Carpenter’s Complete Guide to the SAS Macro Language by Art Carpenter.
You can download the entire code from this post here.