Iterative definition of macro variables

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 9
Accepted Solution

Iterative definition of macro variables

Hello,

 

I try to define macro variables in an iterative loop. An altough the code underneath does what it should (SAS 9.4), we can expect a warning message "apparent symbolic references not resolved". Actually I have no idea how a more elegant solution might look. Can you help me?

 

%MACRO a(XVAR1=, CCENT=, GCENT=);
%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;


%if %sysevalf(%superq(XVAR1)=,boolean) = 0 %then %do; 
	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);
	%Do N1 = 1 %to &NXVAR1;
		%Let a=%scan(&XVAR1,&N1);
		%Let b=%index(&CCENT,&a);
		%Let c=%index(&GCENT,&a);
		%if &b > 0 %then %do;
			%Let X1&N1 = &a.cc;
		%end;
		%else %if &c > 0 %then %do;
			%Let X1&N1 = &a.gc;
		%end;
		%else %do;
			%Let X1&N1 = &a;
		%end;
	%end;
	%let XVAR1n = %namep(&X1,&NXVAR1);
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

%a(XVAR1=xvar1a xvar1b, CCENT=xvar1b, GCENT=xvar1a);

Bye, Daniel       


Accepted Solutions
Solution
‎03-15-2017 04:01 AM
Valued Guide
Posts: 632

Re: Iterative definition of macro variables

First as was mentioned by @ballardw embedded macro definitions are not needed and almost always counter productive.  The macro definitions would appear as:

%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;
%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
....

The better news is that you don't need the %NAMEP macro anyway.  Let's look at your other code a bit.  This portion counts the number of words in &XVAR1.

	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);

This is simplified with the COUNTW function.

	%let NXVAR1 = %sysfunc(countw( &XVAR1));                            

The call to the %NAMEP is causing an error (unitialized variable because &X1 is not defined).  Since you already have a loop. the definition of &XVAR1N can be moved insite the loop.

		%else %do;
			%Let X1&N1 = &a;
		%end;
	  %let XVAR1n = &xvar1n &&x1&n1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

Notice that &XVAR1N is initialized as a local macro variable just below the macro statement. Other cleanup in the macro is possible, but this should get you started.

View solution in original post


All Replies
Super Contributor
Posts: 252

Re: Iterative definition of macro variables

I can't work out exactly what you're trying to do, but is it simply a case of:

	%let XVAR1n = %namep(X1, &NXVAR1);
Super User
Super User
Posts: 7,727

Re: Iterative definition of macro variables

What exactly is it your trying to do?  I can guarentee you thre is a far simpler and easier to maintain way of doing things thatn that, be it re-modelling your data, or using inbuilt SAS functionality.  Creating endless macro lists, macros and such like is a recipe for obfuscatd, unmaintable code which will fall over every time you run it.

Super User
Posts: 11,144

Re: Iterative definition of macro variables

Defining a macro to include another macro, especially one such as your NAMEP that has no dependencies on the parameters of the outmacro is poor practice. As a minimum you waste compute cycles recompiling it everytime the outer macro executes.

 

And it really helps to provide an example of what you expect this macro to produce.

Solution
‎03-15-2017 04:01 AM
Valued Guide
Posts: 632

Re: Iterative definition of macro variables

First as was mentioned by @ballardw embedded macro definitions are not needed and almost always counter productive.  The macro definitions would appear as:

%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;
%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
....

The better news is that you don't need the %NAMEP macro anyway.  Let's look at your other code a bit.  This portion counts the number of words in &XVAR1.

	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);

This is simplified with the COUNTW function.

	%let NXVAR1 = %sysfunc(countw( &XVAR1));                            

The call to the %NAMEP is causing an error (unitialized variable because &X1 is not defined).  Since you already have a loop. the definition of &XVAR1N can be moved insite the loop.

		%else %do;
			%Let X1&N1 = &a;
		%end;
	  %let XVAR1n = &xvar1n &&x1&n1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

Notice that &XVAR1N is initialized as a local macro variable just below the macro statement. Other cleanup in the macro is possible, but this should get you started.

Occasional Contributor
Posts: 9

Re: Iterative definition of macro variables

Thank you for the valuable thoughts and the time that you have spent on my problem.

 

For the sake of completeness here the working code:

 

%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
%if %sysevalf(%superq(XVAR1)=,boolean) = 0 %then %do; 
	%let NXVAR1 = %sysfunc(countw(&XVAR1));                             
	%Do N1 = 1 %to &NXVAR1;
		%Let a=%scan(&XVAR1,&N1);
		%Let b=%index(&CCENT,&a);
		%Let c=%index(&GCENT,&a);
		%if &b > 0 %then %do;
			%Let X1&N1 = &a.cc;
		%end;
		%else %if &c > 0 %then %do;
			%Let X1&N1 = &a.gc;
		%end;
		%else %do;
			%Let X1&N1 = &a;
		%end;
		%let XVAR1n = &XVAR1n &&X1&N1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;
%mend a;

%a(XVAR1=xvar1a xvar1b, CCENT=xvar1b, GCENT=xvar1a);
☑ This topic is solved.

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

Discussion stats
  • 5 replies
  • 201 views
  • 1 like
  • 5 in conversation