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

Hi all,

I try to understand why in below sample macro variable MyMvar doesn't resolve when using call execute().

I understand that this is a timing issue but as simple as the example is, I can't understand the why. Could someone please shed some light on it for me?

%macro testit();
  data _null_;
    call symputx('MyMvar','Test String','L');
    stop;
  run;

  data _null_;
    put "MyMvar: &MyMvar";
    stop;
  run; 

%mend;

data _null_;
  call execute('%testit()');
  stop;
run;

data _null_;
  _rc=dosubl('%testit()');
  stop;
run;
 

 

40         data _null_;
41           call execute('%testit()');
42           stop;
43         run;

WARNING: Apparent symbolic reference MYMVAR not resolved.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      

NOTE: CALL EXECUTE generated line.
1         + data _null_;     call symputx('MyMvar','Test String','L');     stop;   run;

NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      
1         +                                                                                data _null_;     put "MyMvar: &MyMvar";  
         stop;   run;


MyMvar: Test String
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.01 seconds

Thanks,

Patrick

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hi @Patrick,

 

The late Roland Rashleigh-Berry recommended: Use %nrstr() when you "call execute" a macro. And indeed, if you follow this advice the warning does not occur. What he wrote seems to explain what you have observed: "the macro call will be resolved internally" already within the data step containing the CALL EXECUTE statement. So, when the macro processor parses the code of macro TESTIT it stumbles across macro variable reference &MyMvar, hence the warning, because the data step defining MyMvar has not been executed yet (as macro resolution has not yet finished plus we are still in the "outer" data step).

 

With DOSUBL it's a different story because of the "parallel processing" even of data steps which it enables.

View solution in original post

7 REPLIES 7
FreelanceReinh
Jade | Level 19

Hi @Patrick,

 

The late Roland Rashleigh-Berry recommended: Use %nrstr() when you "call execute" a macro. And indeed, if you follow this advice the warning does not occur. What he wrote seems to explain what you have observed: "the macro call will be resolved internally" already within the data step containing the CALL EXECUTE statement. So, when the macro processor parses the code of macro TESTIT it stumbles across macro variable reference &MyMvar, hence the warning, because the data step defining MyMvar has not been executed yet (as macro resolution has not yet finished plus we are still in the "outer" data step).

 

With DOSUBL it's a different story because of the "parallel processing" even of data steps which it enables.

Astounding
PROC Star

CALL EXECUTE is generating two DATA steps.  However, it can't actually run either of them immediately.  Both of them have to wait until the current DATA step (the one that contains CALL EXECUTE) has finished.  Naturally, you just can't run another DATA step until the current DATA step has finished.  

 

Instead, SAS has to stack up the statements that CALL EXECUTE is generating, until the current DATA step has finished.  There's a problem stacking up the PUT statement, because &MYVAR doesn't exist yet.  It only exists after the current DATA step finishes, and the first generated DATA step completes.

Kurt_Bremser
Super User

You might see it like that: call execute() pushes the code contained onto the same execution pipeline that the current data step is running in, while dosubl() creates a new, independent execution pipeline that only exists for the duration of the dosubl() call.

 

If I read it correctly, dosubl() has been added with SAS 9.4 and opens up a whole new way of thinking about timing. At least I can't find a reference in the docs for 9.3 and earlier.

Quentin
Super User

You've already received some great answers.  Just to add a bit, I think the key idea is that when you use CALL EXECUTE to invoke a macro, it will execute the macro.  When the macro executes, it will generate any SAS code (data step code or whatever), resolve all the macro references, and put it on the input stack to be compiled and executed by the SAS data step compiler.  When the macro executes, it will also execute any macro statements immediately.  This causes the timing problem, because if the macro generates macro variables from data step code, the attempt to resolve the macro variables will be made before the macro variables have been generated.

 

If you use CALL EXECUTE to invoke a macro and hide the macro call in %NRSTR(), CALL EXECUTE will not actually execute the macro.  Instead, it just generates the call to the macro and puts the macro call on on the input stack.  The macro is executed after the data step with the call execute has completed.  This lets the timing work out.

 

Here is slightly revised sample code, with a %PUT statement added

 

%macro testit();
  data _null_;
    call symputx('MyMvar','Test String','L');
    stop;
  run;

  %put Macro %nrstr(%put) MyMVar: &MyMVar ;

  data _null_;
    put "Data step put MyMvar: &MyMvar";
    stop;
  run; 

%mend;

If you run it like:

%symdel MyMvar ;

data _null_;
  call execute('%testit()');
run;

The log shows that call execute generated the SAS code generated by %testit. So it executed %testit:

208  data _null_;
209    call execute('%testit()');
210  run;

WARNING: Apparent symbolic reference MYMVAR not resolved.
Macro %put MyMVar: &MyMVar
WARNING: Apparent symbolic reference MYMVAR not resolved.

NOTE: CALL EXECUTE generated line.
1   + data _null_;     call symputx('MyMvar','Test String','L');     stop;   run;


1   +                                                                                data _null_;
    put "Data step put MyMvar: &MyMvar";     stop;   run;

Data step put MyMvar: Test String

Warnings are thrown indicating that &MYMVAR could not resolve on the %PUT statement, or the first time it is seen on the PUT statement.  

Also, note that even though you asked CALL SYMPUTX to make a local macro variable, it still made a global macro variable. Because when CALL SYMPUTX executed, there was no local scope.

 

If you run like:

%symdel MyMvar ;

data _null_;
  call execute('%nrstr(%testit())');
run;

Call execute will generate the macro call, but won't actually execute the macro.  The log shows:

292  data _null_;
293    call execute('%nrstr(%testit())');
294  run;


NOTE: CALL EXECUTE generated line.
1   + %testit()


Macro %put MyMVar: Test String

Data step put MyMvar: Test String

Note that call executed generated the call to %testit, but did not actually executed %testit.  %Testit is executed after the data step with the call execute. So all the timing issues work out.  

 

I always use %NRSTR() when invoking a macro via call execute.  Not only does it make the macro timing work out, it also makes a cleaner log, where you can see the macro calls that were generated.

 

 

BASUG is hosting free webinars Next up: Mike Sale presenting Data Warehousing with SAS April 10 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
Ksharp
Super User

Patrick,

I think @FreelanceReinhar get the point ,add %nrstr() to suppress the warning .

Patrick
Opal | Level 21

Thank you all for your great answers.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 7 replies
  • 1299 views
  • 8 likes
  • 7 in conversation