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

The program is: 

%macro loop(testcd=);
data data2;
    set data;
	if %scan(&testcd.,1) eq 1 %if %length(&testcd.) gt %length(%scan(&testcd.,1)) %then %do; and %scan(&testcd.,2) eq 1 %end; then do;
	    value=1;
	end;
	else if %scan(&testcd.,1) eq 0 %if %length(&testcd.) gt %length(%scan(&testcd.,1)) %then %do; and %scan(&testcd.,2) eq 0 %end; then do;
		value=0;
	end;
run;
%mend;
%loop(testcd=%str(Indx55));

%macro loop2(testcd=);
data aa;
set data;
a=%scan(&testcd.,1);
b=%length(%scan(&testcd.,1));
run;
%mend;
%loop2(testcd=%str(Indx55));

 

The program creates a new column VALUE, my question is that what does the if loop mean? I only know the form like 

if xx then do; xxx; end;

or 

%if xx %then %do; xxx; %end;

But it is

if xx %if xx %then %do; and xxx %end; then do; end; 

which seems abnormal in syntax. But it did run successfully. Does anyone know how to understand this program ?  

 

The data and the data2 in the above program are like this,

data - 

AVISIT INDX55

Week2 0

Week4 0

Week8 1

Week12 1

...

data2 - 

a.PNG

 

Another question is that why %scan(&testcd.,1)=the value of Indx55, while %length(%scan(&testcd.,1))=6? (see %loop2 above)

a.PNG

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hello @Sally_Caffrey,

 


@Sally_Caffrey wrote:

I only know the form like 

if xx then do; xxx; end;

or 

%if xx %then %do; xxx; %end;


These two structures are sufficient to understand the code if you consider in addition that

  1. in a first phase, the macro processor resolves all macro code (%scan(), &testcd., %length(), %if ... %then, %do/%end, etc.)
  2. in the second phase, the resulting SAS code is processed (here: the DATA step is compiled and executed).

So, with your example macro call

%loop(testcd=%str(Indx55));

in the first phase:

  • &testcd. is replaced by Indx55
  • then %scan(Indx55,1) is replaced by Indx55 (the first word in the string "Indx55")
  • %length(Indx55) is replaced by 6 (the length of the string "Indx55")
  • the resulting %IF condition 6 gt 6 evaluates to FALSE, which means that the %DO-%END block following %then is not executed, i.e., the SAS code and ... eq 1 is not generated.

The resulting SAS code passed to the DATA step compiler for further processing in the second phase is:

data data2;
set data;
if Indx55 eq 1 then do;
  value=1;
end;
else if Indx55 eq 0 then do;
  value=0;
end;
run;

(It could be simplified, e.g., by omitting do; and end;. Also, an IN condition could be used: if Indx55 in (0, 1) then value=Indx55;).

 

Similarly, with a macro call like

%loop(testcd=%str(Indx55,Indx66));

the %IF condition is met (13 gt 6) and the resulting SAS code looks like this:

data data2;
set data;
if Indx55 eq 1 and Indx66 eq 1 then do;
  value=1;
end;
else if Indx55 eq 0 and Indx66 eq 0 then do;
  value=0;
end;
run;

 

In the DATA step code generated by macro %LOOP2, called as %loop2(testcd=%str(Indx55));, the statements

a=Indx55;
b=6;

are interpreted as usual: variable a is assigned the value of variable Indx55 and variable b the constant value 6. Again, the timing -- first resolution of macro code, then compilation of DATA step code -- is important.

View solution in original post

6 REPLIES 6
PaigeMiller
Diamond | Level 26

There is no actual loop. And so the macro name is misleading. This code assigns a value of either zero or one to the new variable named VALUE, depending on whether or not certain IF conditions are satisfied. That's all it does is see if the conditions are met. This code seems like a very difficult way to code something that doesn't need to be that difficult.

--
Paige Miller
Sally_Caffrey
Obsidian | Level 7
Thanks PaigeMiller. Yes I agree with you, this program can be simplified to simple data step.
FreelanceReinh
Jade | Level 19

Hello @Sally_Caffrey,

 


@Sally_Caffrey wrote:

I only know the form like 

if xx then do; xxx; end;

or 

%if xx %then %do; xxx; %end;


These two structures are sufficient to understand the code if you consider in addition that

  1. in a first phase, the macro processor resolves all macro code (%scan(), &testcd., %length(), %if ... %then, %do/%end, etc.)
  2. in the second phase, the resulting SAS code is processed (here: the DATA step is compiled and executed).

So, with your example macro call

%loop(testcd=%str(Indx55));

in the first phase:

  • &testcd. is replaced by Indx55
  • then %scan(Indx55,1) is replaced by Indx55 (the first word in the string "Indx55")
  • %length(Indx55) is replaced by 6 (the length of the string "Indx55")
  • the resulting %IF condition 6 gt 6 evaluates to FALSE, which means that the %DO-%END block following %then is not executed, i.e., the SAS code and ... eq 1 is not generated.

The resulting SAS code passed to the DATA step compiler for further processing in the second phase is:

data data2;
set data;
if Indx55 eq 1 then do;
  value=1;
end;
else if Indx55 eq 0 then do;
  value=0;
end;
run;

(It could be simplified, e.g., by omitting do; and end;. Also, an IN condition could be used: if Indx55 in (0, 1) then value=Indx55;).

 

Similarly, with a macro call like

%loop(testcd=%str(Indx55,Indx66));

the %IF condition is met (13 gt 6) and the resulting SAS code looks like this:

data data2;
set data;
if Indx55 eq 1 and Indx66 eq 1 then do;
  value=1;
end;
else if Indx55 eq 0 and Indx66 eq 0 then do;
  value=0;
end;
run;

 

In the DATA step code generated by macro %LOOP2, called as %loop2(testcd=%str(Indx55));, the statements

a=Indx55;
b=6;

are interpreted as usual: variable a is assigned the value of variable Indx55 and variable b the constant value 6. Again, the timing -- first resolution of macro code, then compilation of DATA step code -- is important.

Sally_Caffrey
Obsidian | Level 7
Thanks for such detailed explanation FreelanceReinh! Now I am clear how this loop works.
WarrenKuhfeld
Ammonite | Level 13

Don't write code like that. Just because you can, does not mean you should. When I worked as a SAS developer, I wrote macros that were thousands of lines long and were callable by other macros that were even longer. There were many macro statements, macro functions, and macro variables.  Still, my first rule of macro writing was NEVER use the macro language where you don't have to, and equivalently, ALWAYS use ordinary SAS instead when you can. In a DATA step, that means access the macro variables when you can via SYMGET, process their values in ordinary DATA step variables by using ordinary DATA step statements and functions, and if necessary, send the results into macro variables via SYMPUTX.

Sally_Caffrey
Obsidian | Level 7
Thanks for introduction WarrenKuhfeld. I agree SYMGET is better and will try.

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
  • 6 replies
  • 1043 views
  • 1 like
  • 4 in conversation