MACRO variable inside MACRO

#1
I'm curious why the following code does not work:

Code:
%LET mbr_list=1,2,3,4,5;

%MACRO mbr_loop(mbr_values);
      %let mbr_count=%sysfunc(countw(&mbr_values));
      %do i=1 %to &mbr_count;
      %let mbr=%cmpres(%qscan(&mbr_values,&i,%str(,)));

            %put &mbr;
      %end;
%MEND;

%MBR_LOOP(%str(&mbr_list));

It gives me the following error: Error: More positional parameters found than defined.

However, if I run the exact same macro code except just manually type the numbers 1-5 inside the MBR_LOOP() it will work:

Code:
%LET X=1,2,3,4,5;

%MACRO mbr_loop(mbr_values);
      %let mbr_count=%sysfunc(countw(&mbr_values));
      %do i=1 %to &mbr_count;
      %let mbr=%cmpres(%qscan(&mbr_values,&i,%str(,)));

            %put &mbr;
      %end;
%MEND;

%MBR_LOOP(%str(1,2,3,4,5));

(in the log)
1
2
3
4
5
Can anyone help me put the &MBR_LIST macro inside the %MBR_LOOP(%str());?
 
#2
There are at least two ways to fix this. If you insist on using commas as separators for your list of values then modify the macro as follows:
Code:
%let mbr_list = 1, 2, 3, 4, 5;

%macro mbr_loop /parmbuff;
  %local paramlist
         mbr_count
         i
         mbr;
  %let paramlist = %sysfunc(compress("&syspbuff", %str(0123456789,), K));
  %let mbr_count = %sysfunc(countw(%quote(&paramlist)));
  %do i=1 %to &mbr_count;
    %let mbr = %cmpres(%qscan(%quote(&paramlist),&i,","));
    %put &mbr;
  %end;
%mend;
Both “%mbr_loop(&mbr_list);” and “%mbr_loop(1, 2, 3, 4, 5);” should run without trouble and give the same result.

If spaces are okay as separators, you can do this:
Code:
%let mbr_list = 1 2 3 4 5;

%macro mbr_loop(mbr_values);
  %local mbr_count
         i
         mbr;
  %let mbr_count = %sysfunc(countw(&mbr_values));
  %do i=1 %to &mbr_count;
    %let mbr = %qscan(&mbr_values, &i);
    %put &mbr;
  %end;
%mend;
Both “%mbr_loop(&mbr_list);” and “%mbr_loop(1 2 3 4 5);” should run without trouble and give the same result.

(I have also added a “%local” qualifier because the macro variables that are thus qualified properly have only local scope, not global.)
 
#4
No, there’s no per se issue with the “%str(&macro_name)” construct within a macro definition itself. The problem is that in the SAS world, a macro is just a shorthand label for a blob of text (that can also contain other macros). In your original case, “%mbr_loop(&mbr_list);” resolved to “%mbr_loop(1,2,3,4,5);” which implied that your “%mbr_loop()” macro took five parameters instead of just one. That is, the problem is using commas as value separators without somehow telling SAS that the comma-separated list should actually be treated as a single string argument.

You could also have used “%let mbr_list = %str(1, 2, 3, 4, 5);” for the first line in your code and left everything else the same.