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

Here's my code, I simplified my problem as this:

 

%macro checkrow(dsname);
%let dsid=%sysfunc(open(&dsname));
%let countrow=%sysfunc(attrn(&dsid,nlobs));
%let rc=%sysfunc(close(&dsid));
&countrow
%mend checkrow;


data t1;
input a b $;
datalines;
1 a
2 b
;
run;


%put %checkrow(t1);

 

%macro t2;
data t1;
set t1 t1;
run;
%put %checkrow(t1);
%mend t2;

 

data _null_;
do i = 0 to 3;
call execute('%t2');
end;
run;

 

the macro checkrow is used to check how many rows in a dataset and it works well. But here's the problem

Every iteration in the data_null_, the row of dataset t1 is doubled, so my expectation is 

2

2

4

8

16

But the output is 

2

2

2

2

2

although the actual t2 rows are already 16

Could anyone tell me why? Why the %checkrow(t2) don't work here?

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

Try it this way:

 

data _null_;
do i = 0 to 3;
call execute('%nrstr(%t2)');
end;
run;

 

 

***************** EDITED to explain:

 

CALL EXECUTE asks SAS to execute the statements as soon as possible.  That doesn't mean that they execute when you would expect.

 

When CALL EXECUTE generates DATA and PROC statements, those can't run immediately.  After all, CALL EXECUTE appears in the middle of a DATA step.  So additional DATA and PROC statements have to wait until the current DATA step finishes.

 

However, macro programming statements are able to run immediately, before the current DATA step finishes executing.  So a %LET or %PUT statement, for example, within the definition of %T2 runs right away.

 

%NRSTR temporarily masks the % (in %t2) so that the macro processor doesn't immediately recognize it as being a macro command.  The net effect is that %t2 waits to execute, until the current DATA step is complete.

View solution in original post

8 REPLIES 8
DavidPope
SAS Employee

Per the documentation on call execute(argument)

 

If argument resolves to a SAS statement or if execution of the macro generates SAS statements, the statement(s) execute after the end of the DATA step that contains the CALL EXECUTE routine.

DavidPope
SAS Employee

Use this code instead.

 

%macro checkrow(dsname);

%let dsid=%sysfunc(open(&dsname));

%let countrow=%sysfunc(attrn(&dsid,nlobs));

%let rc=%sysfunc(close(&dsid));

 

&countrow

%mend checkrow;

 

 

data t1;

input a b $;

datalines;

 

1 a

2 b

;

run;

 

 

%put %checkrow(t1);

 

 

%macro t2;

%do i = 0 %to 3;

 

data t1;

set t1 t1;

run;

%put %checkrow(t1);

%end;

%mend t2;

 

%t2;

 

zhaoxuan210
Fluorite | Level 6

Thank you very much for your reply. It works in this condition. Now I know it's the problem of call execute. But in the real case what I'm doing, which is much more complex, I have to make input to the macro %t2, and the input is from other dataset. So is there other way other than call execute that I can use this macro(and also input variables) in a data step?

Astounding
PROC Star

Try it this way:

 

data _null_;
do i = 0 to 3;
call execute('%nrstr(%t2)');
end;
run;

 

 

***************** EDITED to explain:

 

CALL EXECUTE asks SAS to execute the statements as soon as possible.  That doesn't mean that they execute when you would expect.

 

When CALL EXECUTE generates DATA and PROC statements, those can't run immediately.  After all, CALL EXECUTE appears in the middle of a DATA step.  So additional DATA and PROC statements have to wait until the current DATA step finishes.

 

However, macro programming statements are able to run immediately, before the current DATA step finishes executing.  So a %LET or %PUT statement, for example, within the definition of %T2 runs right away.

 

%NRSTR temporarily masks the % (in %t2) so that the macro processor doesn't immediately recognize it as being a macro command.  The net effect is that %t2 waits to execute, until the current DATA step is complete.

zhaoxuan210
Fluorite | Level 6

Wow, it works. Could you briefly explain it a little bit?

Tom
Super User Tom
Super User

@zhaoxuan210 wrote:

Wow, it works. Could you briefly explain it a little bit?


There are two timing issues with CALL EXECUTE().  The main one, as explained in the manual per the post above in this thread, is that the code is stacked up to run after the current data step finishes.

 

The second timing issue is that macro triggers in the string that you pass to CALL EXECUTE() are processed by the macro processor immediately and the resulting code is what makes its way onto the stack to run after the data step runs.  By adding the %NRSTR() into the string that is passed this resolution by the macro processor is delayed until when the code is pulled back off of the stack to execute.

 

For this problem that second timing issue is critical because at the time the CALL EXECUTE() statement runs the dataset that the macro wants to open and examine is still being created!

zhaoxuan210
Fluorite | Level 6

Thank you for your explain! Yes the second timing problem is shown in this case. I'll also be care about the first timing problem. I really think maybe SAS can consider to make some change so that the program runs in the order it looks like.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 8 replies
  • 1004 views
  • 3 likes
  • 4 in conversation