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

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       

1 ACCEPTED SOLUTION

Accepted Solutions
ArtC
Rhodochrosite | Level 12

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

5 REPLIES 5
LaurieF
Barite | Level 11

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

	%let XVAR1n = %namep(X1, &NXVAR1);
RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

ballardw
Super User

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.

ArtC
Rhodochrosite | Level 12

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.

Daniel_Paul
Obsidian | Level 7

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);

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

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