DATA Step, Macro, Functions and more

macro resolution

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 15
Accepted Solution

macro resolution

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;

 


Accepted Solutions
Solution
‎05-20-2017 01:27 PM
Super User
Super User
Posts: 6,499

Re: macro resolution

[ Edited ]

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


All Replies
Solution
‎05-20-2017 01:27 PM
Super User
Super User
Posts: 6,499

Re: macro resolution

[ Edited ]

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;

 

Occasional Contributor
Posts: 15

Re: macro resolution

Tom,

 

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

Super User
Posts: 9,676

Re: macro resolution


options mlogicnest mprintnest mlogic mprint symbolgen;
Occasional Contributor
Posts: 15

Re: macro resolution

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

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

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