macro resolution in call execute

Reply
New Contributor
Posts: 4

macro resolution in call execute

Did the behavior of call execute change recently? As recently a few months ago, when executing a macro with call execute all macro variables would be resolved immediately, and the following would not function properly, because &ind would not exist at the time of compilation and immediately resolve to a blank:


%macro testmacro();

data assign;
ind=1;
call symput('ind',1);
run;

 

data testtable;
a="&ind";
put a;
if &ind=1 then do;
call execute('%finalmacro;');
end;
run;
%mend testmacro;

 

%symdel ind;

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

 

Now however this type of logic seems to have magically started working. While the initial macro print indicates that &ind does not resolve, when the second data step is compiled it re-resolves the macro variable and functions properly. I don't think I'm just going bonkers, as this article describes a situation where call execute will not run a macro properly because of the above reasons. The macro in the section "Timing Considerations" now DOES IN FACT WORK, even though the point of that section is how it won't work because of immediate macro resolution.

http://www.sascommunity.org/planet/blog/category/call-execute/

Super User
Posts: 6,629

Re: macro resolution in call execute

Posted in reply to wrathstone

An educated guess ...

 

Since there is no macro variable named IND as your program begins, this statement gets passed without change:

 

if &ind=1 then do;

 

Then the top DATA step runs and creates &IND, making its value available for the next DATA step.

 

One way to test this:  replace SYMDEL with:

 

%let ind=8;

 

I would imagine you get the "old" behavior:  if 8=1 then do;

New Contributor
Posts: 4

Re: macro resolution in call execute

Posted in reply to Astounding

Interesting. You are correct that if the macro variable already exists at the time of compilation, it will not be recompiled upon reaching the data step that uses it.

I believe this behavior is still distinct from several months ago, when I had several use cases where a macro variable didn't exist going into a macro, and as a result of call execute was not being resolved by the second data step.

Super User
Posts: 9,880

Re: macro resolution in call execute

Posted in reply to wrathstone

Which SAS version are you at?

I tested your code both with EG 4.3 on SAS 9.2 and EG 7.1 on SAS 9.4 TS1M2, and got identical logs:

1          ;*';*";*/;quit;run;
2          OPTIONS PAGENO=MIN;
3          %LET _CLIENTTASKLABEL='Programm';
4          %LET _CLIENTPROJECTPATH='';
5          %LET _CLIENTPROJECTNAME='';
6          %LET _SASPROGRAMFILE=;
7          
8          ODS _ALL_ CLOSE;
9          OPTIONS DEV=ACTIVEX;
NOTE: Procedures may not support all options or statements for all devices. For details, see the documentation for each procedure.
10         GOPTIONS XPIXELS=0 YPIXELS=0;
11         ODS LISTING GPATH=&sasworklocation;
12         FILENAME EGHTML TEMP;
13         ODS HTML(ID=EGHTML) FILE=EGHTML ENCODING='utf-8' STYLE=Analysis
13       ! STYLESHEET=(URL="file:///C:/Program%20Files/SAS/EnterpriseGuide/4.3/Styles/Analysis.css")
13       ! ATTRIBUTES=("CODEBASE"="http://www2.sas.com/codebase/graph/v92/sasgraph.exe#version=9,2") NOGTITLE NOGFOOTNOTE
13       ! GPATH=&sasworklocation;
NOTE: Writing HTML(EGHTML) Body file: EGHTML
14         
15         GOPTIONS ACCESSIBLE;
16         %macro testmacro();
17         
18         data assign;
19         ind=1;
20         call symput('ind',1);
21         run;
22         
23         
24         
25         data testtable;
26         a="&ind";
27         put a;
28         if &ind=1 then do;
29         call execute('%finalmacro;');
30         end;
31         run;
32         %mend testmacro;
33         
34         
35         
36         %symdel ind;
WARNING: Attempt to delete macro variable IND failed. Variable not found.
37         
38         data _null_;
39         call execute('%testmacro;');
40         run;

WARNING: Apparent symbolic reference IND not resolved.
WARNING: Apparent symbolic reference IND 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 assign; ind=1; call symput('ind',1); run;

2                                                          The SAS System                          08:48 Wednesday, October 18, 2017

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
      1:40   
NOTE: The data set WORK.ASSIGN has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds
      
1         +                                                    data testtable; a="&ind"; put a; if &ind=1 then do; call 
      execute('%finalmacro;'); end; run;;


1
WARNING: Apparent invocation of macro FINALMACRO not resolved.
NOTE: The data set WORK.TESTTABLE has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      

NOTE: CALL EXECUTE generated line.
NOTE: Line generated by the CALL EXECUTE routine.
1         + %finalmacro;
            _
            180
WARNING: Apparent invocation of macro FINALMACRO not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

41         
42         GOPTIONS NOACCESSIBLE;
43         %LET _CLIENTTASKLABEL=;
44         %LET _CLIENTPROJECTPATH=;
45         %LET _CLIENTPROJECTNAME=;
46         %LET _SASPROGRAMFILE=;
47         
48         ;*';*";*/;quit;run;
49         ODS _ALL_ CLOSE;
50         
51         
52         QUIT; RUN;
53         

9.4:

1                                                          Das SAS System                          07:54 Wednesday, October 18, 2017

1          ;*';*";*/;quit;run;
2          OPTIONS PAGENO=MIN;
3          %LET _CLIENTTASKLABEL='Programm (3)';
4          %LET _CLIENTPROJECTPATH='';
5          %LET _CLIENTPROJECTNAME='';
6          %LET _SASPROGRAMFILE=;
7          
8          ODS _ALL_ CLOSE;
9          OPTIONS DEV=ACTIVEX;
10         GOPTIONS XPIXELS=0 YPIXELS=0;
11         ODS LISTING GPATH=&sasworklocation;
12         FILENAME EGSR TEMP;
13         ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
14             STYLE=HtmlBlue
15             STYLESHEET=(URL="file:///C:/Program%20Files/SASHome/SASEnterpriseGuide/7.1/Styles/HtmlBlue.css")
16             NOGTITLE
17             NOGFOOTNOTE
18             GPATH=&sasworklocation
19             ENCODING=UTF8
20             options(rolap="on")
21         ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
22         
23         GOPTIONS ACCESSIBLE;
24         %macro testmacro();
25         
26         data assign;
27         ind=1;
28         call symput('ind',1);
29         run;
30         
31         
32         
33         data testtable;
34         a="&ind";
35         put a;
36         if &ind=1 then do;
37         call execute('%finalmacro;');
38         end;
39         run;
40         %mend testmacro;
41         
42         
43         
44         %symdel ind;
WARNING: Attempt to delete macro variable IND failed. Variable not found.
45         
46         data _null_;
47         call execute('%testmacro;');
48         run;

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

2                                                          Das SAS System                          07:54 Wednesday, October 18, 2017

NOTE: CALL EXECUTE generated line.
1         + data assign; ind=1; call symput('ind',1); run;

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
      1:40   
NOTE: The data set WORK.ASSIGN has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      
1         +                                                    data testtable; a="&ind"; put a; if &ind=1 then do; call 
      execute('%finalmacro;'); end; run;;


1
WARNING: Apparent invocation of macro FINALMACRO not resolved.
NOTE: The data set WORK.TESTTABLE has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      

NOTE: CALL EXECUTE generated line.
NOTE: Line generated by the CALL EXECUTE routine.
1         + %finalmacro;
            _
            180
WARNING: Apparent invocation of macro FINALMACRO not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

49         
50         GOPTIONS NOACCESSIBLE;
51         %LET _CLIENTTASKLABEL=;
52         %LET _CLIENTPROJECTPATH=;
53         %LET _CLIENTPROJECTNAME=;
54         %LET _SASPROGRAMFILE=;
55         
56         ;*';*";*/;quit;run;
57         ODS _ALL_ CLOSE;
58         
59         
60         QUIT; RUN;
61         
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
New Contributor
Posts: 4

Re: macro resolution in call execute

[ Edited ]
Posted in reply to KurtBremser

Yeah, honestly I don't understand what would have changed. Maybe there's some obscure SAS option that got tripped? I am on SAS 9.4

But when I first discovered that call execute had this behavior, it was breaking several of my macros (as the programs we use almost exclusively are generated by call executes in a central program), and I tested thoroughly to be sure I understood the mechanics. I went back to my old code, and the macros I wrote to test it now work, when I know they definitely didn't before...

But since I can't really reproduce that, what about that SAS community article I posted, with the section on timing of resolution? Am I totally missing something, because he posts a macro as an example of how immediate macrovar resolution breaks things. But as far as I can tell it runs just fine and the variable list created in the earlier proc sql is used successfully by the subsequent data step. Why would he have written this section if it was working?

 

edit: to look at his notes on that example macro, maybe he's just referring to the execution of the %put with the number of observations. oh well.

Ask a Question
Discussion stats
  • 4 replies
  • 183 views
  • 0 likes
  • 3 in conversation