With a data step, I can put a macro variable inside another one:
data _null_;
call symput('b','&a');
run;
So &a is now inside b.
Check:
%let a=33;
%put &b;
==> 33
%let a=44;
%put &b;
==> 44
How can I do the same without a datastep, with pure macro programming?
So the code should look like:
%let b= ???(&a);
%let a=33;
%put &b;
%let a=44;
%put &b;
Note that I want to use &b without unquoting. With unquoting it is easy:
%let b=%nrstr(&a);
%let a=33;
%put --- %unquote(&b);
%let a=44;
%put --- %unquote(&b);
But that is not what I want.
/* Here is a data-step free solution */
%let b=&&%unquote(a);
%let a=33;
%put &b;
%let a=44;
%put &b;
/* If you dislike the %UNQUOTE function and know the ASCII table, try this */
%let b=&&%sysfunc(byte(97));
%let a=33;
%put &b;
%let a=44;
%put &b;
/* Similar, but showing the "a" in the definition of b: */
%let b=&&%sysfunc(byte(%sysfunc(rank(a))));
%let a=33;
%put &b;
%let a=44;
%put &b;
/* Yet another option: */
%let b=&&%sysfunc(cat(a));
%let a=33;
%put &b;
%let a=44;
%put &b;
I believe this magic is not possible as a function style macro.
When passing a value to a macro variable which contains an ampersand you must quote the value however you code it.
You could of course wrap your data step into a macro and then call this macro with two parameters.
%macro not_so_magic(l,r);
%global &l;
data _null_;
call symput("&l",'&'||"&r");
run;
%mend;
%not_so_magic(b,a)
%let a=33;
%put &=b;
%let a=44;
%put &=b;
What about this?
%let c=%sysfunc(dosubl(data _null_; call symput('b','&a'); run;));
%let a=33;
%put &b;
%let a=44;
%put &b;
Ok, it says "%let c=...", not "%let b=...", but what's in a name, after all?
Its not that I need the solution for any project.
I just want to learn about macro and how I can put &a into b.
/* Here is a data-step free solution */
%let b=&&%unquote(a);
%let a=33;
%put &b;
%let a=44;
%put &b;
/* If you dislike the %UNQUOTE function and know the ASCII table, try this */
%let b=&&%sysfunc(byte(97));
%let a=33;
%put &b;
%let a=44;
%put &b;
/* Similar, but showing the "a" in the definition of b: */
%let b=&&%sysfunc(byte(%sysfunc(rank(a))));
%let a=33;
%put &b;
%let a=44;
%put &b;
/* Yet another option: */
%let b=&&%sysfunc(cat(a));
%let a=33;
%put &b;
%let a=44;
%put &b;
Nice! The doubled ampersand allows you to pass in the ampersand without quoting and after that anything will do that allows to pass in the 'a' without adding a quote to the ampersand but still in a way that the tokenizer doesn't treat it as a macro variable.
Here another option
%let b=&&%left(a);
%let a=33;
%put b has value: &b;
%let a=44;
%put b has value: &b;
BTW, if you want to look what is "really" in &b, use %superq(b)
The question I wouold ask is why? I find that 99% of tasks can be done in Base SAS. Macro is a utility language to help in generate repeating code and such like, its just a text generator at the end of the day. If I come across a program which has more than one ampersand or percentage in a line, I just delete the program and start again. Have yet to see a valid reason for resorting to macro when re-shaping of data and array/aggregates don't do the same job.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.