BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
grezek
Obsidian | Level 7

I'm on Win7 Pro release 9.4 TS1M4

I would like to code below to produce:

exp_m_EL_unempl_down20

but I can't see to get the nested Unempl_perc1 macro variable to resolve.

Any suggestions are welcome.  Thank you.  -- George Rezek

code:

 

data _null_ ;

call symput('invar1','unempl') ;

call symput('product1','1st_mtg') ;

call symput('unempl_perc1','_down20') ;

call symput('gvar1','exp_m_EL') ;

run ;

%macro fuss ;

%do i = 1 %to 1 ; %put "stick1 &&invar&i.." ;

*loop through the products ;

%do j = 1 %to 1 ; %put "stick2 &&product&j.." ;

*loop through the graph variables ;

%do k = 1 %to 1 ; %put "stick3 &&gvar&k.." ;

%put "&&invar&i.._perc1 &invar1. &unempl_perc1." ;

%put "&&&gvar&k.._&&&&invar&i.._perc1. ";

%end ;%end ;%end ;run ;%mend fuss ;run;

%fuss ;

run;

 

log:

 

1104

1105 data _null_ ;

1106 call symput('invar1','unempl') ;

1107 call symput('product1','1st_mtg') ;

1108 call symput('unempl_perc1','_down20') ;

1109 call symput('gvar1','exp_m_EL') ;

1110 run ;

NOTE: DATA statement used (Total process time):

real time 0.00 seconds

cpu time 0.01 seconds

 

1111 %macro fuss ;

1112 %do i = 1 %to 1 ; %put "stick1 &&invar&i.." ;

1113 *loop through the products ;

1114 %do j = 1 %to 1 ; %put "stick2 &&product&j.." ;

1115 *loop through the graph variables ;

1116 %do k = 1 %to 1 ; %put "stick3 &&gvar&k.." ;

1117 %put "&&invar&i.._perc1 &invar1. &unempl_perc1." ;

1118 %put "&&&gvar&k.._&&&&invar&i.._perc1. ";

1119 %end ;%end ;%end ;run ;%mend fuss ;run;

1120 %fuss ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

"stick1 unempl"

MPRINT(FUSS): *loop through the products ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable J resolves to 1

SYMBOLGEN: Macro variable PRODUCT1 resolves to 1st_mtg

"stick2 1st_mtg"

MPRINT(FUSS): *loop through the graph variables ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable K resolves to 1

SYMBOLGEN: Macro variable GVAR1 resolves to exp_m_EL

"stick3 exp_m_EL"

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

SYMBOLGEN: Macro variable UNEMPL_PERC1 resolves to _down20

"unempl_perc1 unempl _down20"

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Unable to resolve the macro variable reference &gvar

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable K resolves to 1

SYMBOLGEN: && resolves to &.

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable GVAR1 resolves to exp_m_EL

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

"exp_m_EL_unempl_perc1. "

MPRINT(FUSS): run ;

1121 run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Macro arrays (a name commonly used for a series of macro variables with numeric suffices) are generally more confusion than they are worth.  If you can find another way to do what you want without using them I recommend it.

 

The rules for multiple & are simple. If there are two together then they are replaced by one and the macro process will scan the result for more macro resolutions.  Let's simplify your example.  You have one array member (INVAR1) that you want to use as part of the name of another array member (UNEMPL_perc1). 

%let invar1=unempl;
%let unempl_perc1= _down20;

First let's see how to generate references to these two variables using a dynamic numeric suffix.

%let i=1;
%put '&&invar&i' &&invar&i ;
%put '&&unempl_perc&i' &&unempl_perc&i ;

Second we can combine them together (and remember to add in periods to let macro processor know where macro references end). 

%put '&&invar&i.._perc&i' &&invar&i.._perc&i;

But that just returns the NAME of the macro variable.  To get it to resolve that name into a value we need to add more &.

%put '&&&&&&invar&i.._perc&i' &&&&&&invar&i.._perc&i;

To see why break it down into the individual passes that the macro process makes on the string.

%put 'Pass 1 = &&&invar1._perc1' &&&invar1._perc1;
%put 'Pass 2 = &unempl_perc1' &unempl_perc1;
%put 'Pass 3 = _down20';

The first pass will replace the '&i.' with their values and all of the double '&&' with single '&'.

The second pass will replace '&invar1' with its value and replace the double '&&' with a single '&'.

Now on the third and final pass the value of '&unempl_perc1' is replaced with its value.

 

Note that it is probably easier and clearer to others if you build the name first and then expand the value of the name.

%let mvar=&&invar&i.._perc&i;
%put &&&mvar;

 

View solution in original post

4 REPLIES 4
Tom
Super User Tom
Super User

Macro arrays (a name commonly used for a series of macro variables with numeric suffices) are generally more confusion than they are worth.  If you can find another way to do what you want without using them I recommend it.

 

The rules for multiple & are simple. If there are two together then they are replaced by one and the macro process will scan the result for more macro resolutions.  Let's simplify your example.  You have one array member (INVAR1) that you want to use as part of the name of another array member (UNEMPL_perc1). 

%let invar1=unempl;
%let unempl_perc1= _down20;

First let's see how to generate references to these two variables using a dynamic numeric suffix.

%let i=1;
%put '&&invar&i' &&invar&i ;
%put '&&unempl_perc&i' &&unempl_perc&i ;

Second we can combine them together (and remember to add in periods to let macro processor know where macro references end). 

%put '&&invar&i.._perc&i' &&invar&i.._perc&i;

But that just returns the NAME of the macro variable.  To get it to resolve that name into a value we need to add more &.

%put '&&&&&&invar&i.._perc&i' &&&&&&invar&i.._perc&i;

To see why break it down into the individual passes that the macro process makes on the string.

%put 'Pass 1 = &&&invar1._perc1' &&&invar1._perc1;
%put 'Pass 2 = &unempl_perc1' &unempl_perc1;
%put 'Pass 3 = _down20';

The first pass will replace the '&i.' with their values and all of the double '&&' with single '&'.

The second pass will replace '&invar1' with its value and replace the double '&&' with a single '&'.

Now on the third and final pass the value of '&unempl_perc1' is replaced with its value.

 

Note that it is probably easier and clearer to others if you build the name first and then expand the value of the name.

%let mvar=&&invar&i.._perc&i;
%put &&&mvar;

 

grezek
Obsidian | Level 7

Tom,

 

Thank you very much for your solution and detailed explanation.  This helps me out quite a bit!  -- George

Ksharp
Super User

options mlogicnest mprintnest mlogic mprint symbolgen;
grezek
Obsidian | Level 7

Mlogicnest and mprintnest --I'd never seen these.  Thank you very much!

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1024 views
  • 0 likes
  • 3 in conversation