Version = Release: 3.7 (Enterprise Edition)
Hi, suppose I have this Macro:
%macro test(p1,p2);
%put &p1.;
%put &p2.;
%mend test;
And sometimes when I call it, the value of p2 depends on p1:
%test(p1=peas,p2=&p1. and carrots);
This works fine but I receive a warning:
WARNING: Apparent symbolic reference P1 not resolved.
68
69 %test(p1=peas,p2=&p1. and carrots);
P1=peas
P2=peas and carrots
Is there a way to suppress this warning?
Thank you
It works because the macro call has caused the macro parser to treat the && and your macro call as two separate tokens. Normally if you type &&p1 the macro processor will convert && to & and then continue to resolve the token and try to resolve &p1. But adding the macro call around p1 it does not do that second round of evaluation. So the &p1 is passed into the macro as the value of P2.
Note that you should use the %UPCASE() function instead of calling the SAS supplied %LOWCASE() macro.
Use %UPCASE() instead because that is macro function (part of the actual SAS language).
Also the SAS supplied macro %LOWCASE is not that well written. It will cause errors if try to call it with values that contain commas.
567 %put %lowcase(a,b); ERROR: More positional parameters found than defined.
Here is a replacement for the limited %LOWCASE() macro that SAS sends.
%macro lowcase/parmbuff;
%if %length(&syspbuff)>2 %then %sysfunc(lowcase&syspbuff);
%mend;
570 %macro lowcase/parmbuff; 571 %if %length(&syspbuff)>2 %then %sysfunc(lowcase&syspbuff); 572 %mend; 573 574 575 %put %lowcase; 576 %put %lowcase(); 577 %put %lowcase(a,b); a,b
When you call the macro via
%test(p1=peas,p2=&p1. and carrots);
then at this point, &p1 is not defined. So the WARNING is correct.
You could, if you want, do something like this:
%let word=peas;
%test(p1=&word,p2=&word and carrots)
And sometimes when I call it, the value of p2 depends on p1:
If it is only sometimes then make that happen in the process of generating the call.
%let x=peas;
%test(p1=&x,p2=&x and carrots)
You can get that effect if you reference another parameter's value in the default values assigned in DEFINITION of the macro.
%macro test(p1=peas,p2=&p1 and carrots);
%put ACTUAL P1=%superq(p1) P2=%superq(p2);
%put RESULT &=p1 &=p2;
%mend test;
276 %test; ACTUAL P1=peas P2=&p1 and carrots RESULT P1=peas P2=peas and carrots
But if you try to use macro quoting to pass in the &p1 then your macro will have to do something to remove the macro quoting.
%macro test(p1,p2);
%put ACTUAL P1=%superq(p1) P2=%superq(p2);
%put RESULT &=p1 &=p2;
%let p1=%unquote(&p1);
%let p2=%unquote(&p2);
%put AFTER &=p1 &=p2;
%mend test;
300 %test(peas,%nrstr(&p1) and carrots); ACTUAL P1=peas P2=&p1 and carrots RESULT P1=peas P2=&p1 and carrots AFTER P1=peas P2=peas and carrots
Thanks for the answers. I think creating another macrovariable before the macro call is going to be the best approach.
I also tried this, which seems to work:
%macro test(p1,p2);
%put &=p1.;
%put &=p2.;
%mend;
%test(p1=peas,p2=&&%lowcase(p1) and carrots);
69 %macro test(p1,p2); 70 %put &=p1.; 71 %put &=p2.; 72 %mend; 73 74 %test(p1=peas,p2=&&%lowcase(p1) and carrots); P1=peas P2=peas and carrots
But why does it work? And why shouldn't I use it?
It works because the macro call has caused the macro parser to treat the && and your macro call as two separate tokens. Normally if you type &&p1 the macro processor will convert && to & and then continue to resolve the token and try to resolve &p1. But adding the macro call around p1 it does not do that second round of evaluation. So the &p1 is passed into the macro as the value of P2.
Note that you should use the %UPCASE() function instead of calling the SAS supplied %LOWCASE() macro.
Use %UPCASE() instead because that is macro function (part of the actual SAS language).
Also the SAS supplied macro %LOWCASE is not that well written. It will cause errors if try to call it with values that contain commas.
567 %put %lowcase(a,b); ERROR: More positional parameters found than defined.
Here is a replacement for the limited %LOWCASE() macro that SAS sends.
%macro lowcase/parmbuff;
%if %length(&syspbuff)>2 %then %sysfunc(lowcase&syspbuff);
%mend;
570 %macro lowcase/parmbuff; 571 %if %length(&syspbuff)>2 %then %sysfunc(lowcase&syspbuff); 572 %mend; 573 574 575 %put %lowcase; 576 %put %lowcase(); 577 %put %lowcase(a,b); a,b
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.