I use nested macro, upper-level and lower-level ones. As seen below (I modified the code a bit to display here), my lower-level macro take &xtr_var for its arguments, so I use %nrstr in the argument for %upper. But the issue I face now is that SAS can't resolve lower-level macro's arguments, i.e., listname and new. Could anybody help me to solve this issue?
%upper (statement= %nrstr(
%lower(listname=set_list, new= &xth_var);%put &set_list;
....
)
WARNING: Apparent symbolic reference LISTNAME not resolved. &listname WARNING: Apparent symbolic reference NEW not resolved. &new
Show us a larger part of the code, including the definitions of the macros. Run the command
options mprint mlogic symbolgen;
and then show us the entire log (not just the errors and warnings).
Also the part you show has imbalanced parentheses.
Why use %NRSTR() here anyway? Why not call %LOWER inside %UPPER instead of using %NRSTR() to include %LOWER as an argument?
Thanks. The below is my code.
%macro loop3 (list1=, statement=);
%if &list1= %then %let N1= 1; %else
%do; %let N1= %sysfunc(countw(&list1)); %end;
%do x= 1 %to &N1;
%let xth_var= %scan(&list1, &x);
%unquote(&STATEMENT);
%end;
%mend;
%macro let_cumulative (listname, new, RepeatedNo);
%if &RepeatedNo= 1 %then
%do; %global &listname; %end;
%else
%do; %let &listname= &&&listname &new; %end;
/* %put "list after=" &listname;*/
%mend;
option mlogic mprint symbolgen;
%symdel set_list;
%loop3 (list1= 1 2 3, statement= %nrstr(
%let_cumulative (listname=set_list, new= &xth_var,RepeatedNo=&x);%put &set_list;
%put &listname;
%put &new;
%put &RepatedNo;
/* %let addset= rcult.r_comp_&xth_var.;*/
/* %let set_list= &set_list &addset;*/
));
%put &set_list;
The below is printed in the log window.
6823 6824 %macro loop3 (list1=, statement=); 6825 %if &list1= %then %let N1= 1; %else 6826 %do; %let N1= %sysfunc(countw(&list1)); %end; 6827 %do x= 1 %to &N1; 6828 %let xth_var= %scan(&list1, &x); 6829 %unquote(&STATEMENT); 6830 %end; 6831 %mend; 6832 6833 %macro let_cumulative (listname, new, RepeatedNo); 6834 %if &RepeatedNo= 1 %then 6835 %do; %global &listname; %end; 6836 %else 6837 %do; %let &listname= &&&listname &new; %end; 6838 /* %put "list after=" &listname;*/ 6839 %mend; 6840 6841 option mlogic mprint symbolgen; 6842 %symdel set_list; 6843 %loop3 (list1= 1 2, statement= %nrstr( MLOGIC(LOOP3): Beginning execution. 6844 %let_cumulative (listname=set_list, new= &xth_var,RepeatedNo=&x);%put &set_list; 6845 %put &listname; 6846 %put &new; 6847 %put &RepatedNo; 6848 /* %let addset= rcult.r_comp_&xth_var.;*/ 6849 /* %let set_list= &set_list &addset;*/ 6850 )); MLOGIC(LOOP3): Parameter LIST1 has value 1 2 MLOGIC(LOOP3): Parameter STATEMENT has value let_cumulative (listnameset_list new xth_varRepeatedNox)put set_list put listname put new put RepatedNo SYMBOLGEN: Macro variable LIST1 resolves to 1 2 MLOGIC(LOOP3): %IF condition &list1= is FALSE MLOGIC(LOOP3): %LET (variable name is N1) SYMBOLGEN: Macro variable LIST1 resolves to 1 2 SYMBOLGEN: Macro variable N1 resolves to 2 MLOGIC(LOOP3): %DO loop beginning; index variable X; start value is 1; stop value is 2; by value is 1. MLOGIC(LOOP3): %LET (variable name is XTH_VAR) SYMBOLGEN: Macro variable LIST1 resolves to 1 2 SYMBOLGEN: Macro variable X resolves to 1 SYMBOLGEN: Macro variable STATEMENT resolves to %let_cumulative (listname=set_list, new= &xth_var,RepeatedNo=&x);%put &set_list; %put &listname; %put &new; %put &RepatedNo; SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been unquoted for printing. MLOGIC(LET_CUMULATIVE): Beginning execution. SYMBOLGEN: Macro variable XTH_VAR resolves to 1 SYMBOLGEN: Macro variable X resolves to 1 MLOGIC(LET_CUMULATIVE): Parameter LISTNAME has value set_list MLOGIC(LET_CUMULATIVE): Parameter NEW has value 1 MLOGIC(LET_CUMULATIVE): Parameter REPEATEDNO has value 1 SYMBOLGEN: Macro variable REPEATEDNO resolves to 1 MLOGIC(LET_CUMULATIVE): %IF condition &RepeatedNo= 1 is TRUE MLOGIC(LET_CUMULATIVE): %GLOBAL &LISTNAME SYMBOLGEN: Macro variable LISTNAME resolves to set_list MLOGIC(LET_CUMULATIVE): Ending execution. MPRINT(LOOP3): ; SYMBOLGEN: Macro variable SET_LIST resolves to WARNING: Apparent symbolic reference LISTNAME not resolved. &listname WARNING: Apparent symbolic reference NEW not resolved. &new WARNING: Apparent symbolic reference REPATEDNO not resolved. &RepatedNo MPRINT(LOOP3): ; MLOGIC(LOOP3): %DO loop index variable X is now 2; loop will iterate again. MLOGIC(LOOP3): %LET (variable name is XTH_VAR) SYMBOLGEN: Macro variable LIST1 resolves to 1 2 SYMBOLGEN: Macro variable X resolves to 2 SYMBOLGEN: Macro variable STATEMENT resolves to %let_cumulative (listname=set_list, new= &xth_var,RepeatedNo=&x);%put &set_list; %put &listname; %put &new; %put &RepatedNo; SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been unquoted for printing. MLOGIC(LET_CUMULATIVE): Beginning execution. SYMBOLGEN: Macro variable XTH_VAR resolves to 2 SYMBOLGEN: Macro variable X resolves to 2 MLOGIC(LET_CUMULATIVE): Parameter LISTNAME has value set_list MLOGIC(LET_CUMULATIVE): Parameter NEW has value 2 MLOGIC(LET_CUMULATIVE): Parameter REPEATEDNO has value 2 SYMBOLGEN: Macro variable REPEATEDNO resolves to 2 MLOGIC(LET_CUMULATIVE): %IF condition &RepeatedNo= 1 is FALSE SYMBOLGEN: Macro variable LISTNAME resolves to set_list MLOGIC(LET_CUMULATIVE): %LET (variable name is set_list) SYMBOLGEN: && resolves to &. SYMBOLGEN: Macro variable LISTNAME resolves to set_list SYMBOLGEN: Macro variable SET_LIST resolves to SYMBOLGEN: Macro variable NEW resolves to 2 MLOGIC(LET_CUMULATIVE): Ending execution. MPRINT(LOOP3): ; SYMBOLGEN: Macro variable SET_LIST resolves to 2 2 WARNING: Apparent symbolic reference LISTNAME not resolved. &listname WARNING: Apparent symbolic reference NEW not resolved. &new WARNING: Apparent symbolic reference REPATEDNO not resolved. &RepatedNo MPRINT(LOOP3): ; MLOGIC(LOOP3): %DO loop index variable X is now 3; loop will not iterate again. MLOGIC(LOOP3): Ending execution. 6851 %put &set_list; SYMBOLGEN: Macro variable SET_LIST resolves to 2 2
SYMBOLGEN: Macro variable SET_LIST resolves to
SET_LIST resolves to
and then nothing is shown. You have not provided a value for SET_LIST, so nothing after that will work.
I still suspect you have overcomplicated the whole thing, and maybe something like this would be easier to code and debug and understand. I show the outline of the code only (and I have no idea what this code is supposed to do anyway):
%macro loop3(list1=,statement=,new=,repeatedno=);
%if &list1= %then %let N1= 1;
%else %do;
%let N1= %sysfunc(countw(&list1));
%end;
%do x= 1 %to &N1;
%let xth_var= %scan(&list1, &x);
%let_cumulative(listname=set_list,new=x&th_var,repeatedno=&x)
...
%mend;
%macro let_cumulative(listname=,new=,repeatedno=);
...
%mend;
As I said, I think it could be simplified even further, but I don't know what you are trying to do.
Lastly, I absolutely hate the idea of a macro whose name begins with %LET such as %LET_CUMULATIVE, because %LET is a command with a specific meaning is the macro processor.
What the heck are you actually trying to do?
Anyway the "statements" you are passing to LOOP3 three don't make much sense. You are trying to reference the parameters (like LISTNAME) to the %LET_CUMULATIVE() macro outside of that macro's scope. Those are LOCAL macro variables to that macro and disappear when the macro is finished running.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.