LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (December 2002, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Thu, 12 Dec 2002 09:26:28 -0500
Reply-To:     Ian Whitlock <WHITLOI1@WESTAT.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Ian Whitlock <WHITLOI1@WESTAT.COM>
Subject:      Re: recruiting cheesy, sleasy SAS tricks tip call execute
Comments: To: "Fehd, Ronald J. (PHPPO)" <rjf2@CDC.GOV>
Comments: cc: "michael@BASSETTCONSULTING.COM" <michael@BASSETTCONSULTING.COM>
Content-Type: text/plain; charset="iso-8859-1"

Ron,

You say:

> NOTE: call execute will not work correctly, > i.e., as you expect, > when you pass a complex macro call to it. > a macro with complexity is one that has symput, > or macro control statements: %IF or %DO, etc.

There two things wrong with this. Complexity and the use of macro %IF, %DO, etc. have nothing to do with the problems caused by invoking macros with CALL EXECUTE. On the other hand, SYMPUT definitely causes problems in most cases, but it is not the only problem. It is far better to understand the problem.

SAS is a sequentially step oriented language. Hence one cannot execute one step inside another. Macros generate code which may consist of steps. When a macro is invoked during SAS compile time, after each step is generated (i.e. when the word scanner reaches a step boundary) execution of the step takes place. This means that the produce of a step in a macro may be used in a subsequent part of the macro. (This is essentially why step boundaries are so much more important in macro than in plain SAS.)

When a macro is invoked via CALL EXECUTE it is during the execution of a DATA step. This has consequences that should be spelled out.

The steps of the macro are generated, but neither compiled nor executed until the executing DATA step finishes execution.

Consequently, any produce of an executed step generated by the macro will not be available during the generation of any SAS code by the macro. It is also true that no macro instructions in the macro can use this produce either. The use of CALL SYMPUT to assign a value to a macro variable is a simple and most important example. However, the same problems arise when using CALL EXECUTE in a generated DATA step, or when generated SQL code is used to create a macro variable. Is this a complete list? I have always been careful to leave the door open to other possibilities. Here is the simplest example I have found so far.

%macro q ;

data q ; x = "HELLO from dataset Q" ; run ;

title "Print of Dataset &syslast" ;

%mend q ;

data w ; x = 1 ; run ;

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

proc print data = q ; run ;

Note the macro has only one step and one global statement. No macro instructions are used with the exception of the reference to one system provided macro variable. However, the title on the subsequent print will be incorrect because the principle given above was violated.

I consider the use of %NRSTR to postpone the execution of the macro until after the executing DATA step far too important to be included in any list of sleazy tricks. I even resent calling it a trick. In fact I wish SI would add a new routine CALL NREXECUTE to facilitate this type of code. If there is any sleaze in CALL EXECUTE, it lies in the lack of programmer control over the log.

IanWhitlock@westat.com -----Original Message----- From: Fehd, Ronald J. (PHPPO) [mailto:rjf2@CDC.GOV] Sent: Wednesday, December 11, 2002 8:58 AM To: SAS-L@LISTSERV.UGA.EDU Subject: Re: recruiting cheesy, sleasy SAS tricks tip call execute

> From: Michael L. Davis [mailto:michael@BASSETTCONSULTING.COM] > I'd like to do a Coder's Corner presentation at NESUG next > year on the subject of "Cheesy, Sleasy SAS Tricks". > - Michael "Mad Doggy" Davis

What a pile of bones you are collecting here, MadDog! Don't know the cheese factor of this one. maybe ToFu?! LOL %-D

This is a trick I use for debugging call execute

enabling the mVar CMD=put Cmd; will write your call execute statements to file PRINT; once they look correct then disable that statement. and your code executes.

using NoRescanString inside call execute guarantees that macro calls in Cmd will execute when popped not pushed.

NOTE: call execute will not work correctly, i.e., as you expect, when you pass a complex macro call to it. a macro with complexity is one that has symput, or macro control statements: %IF or %DO, etc.

DATA X;MemName='X';output;stop;run; %*note:MemName is available from DICTIONARY.TABLES;

%LET CMD = call execute('%nrstr(' !! Cmd !! ');' ); %LET CMD = put Cmd;%*TESTING;

%LET LIBREF = WORK; %LET DATA = X; %LET CONDITION =1;%*for testing;

%MACRO TEST1(DATA=);PROC FREQ data = &DATA.;run;%MEND; %MACRO TEST2(DATA=,COND=); %IF &COND. %THEN %DO; PROC FREQ data = &DATA.;run;%END;%MEND; DATA _NULL_; length Cmd $ 72;%*may be longer; file PRINT; do until(EndoFile); set WORK.&DATA. (where = (&CONDITION.)) end = EndoFile; Cmd = "proc PRINT data = &LIBREF.." !! trim(MemName) !! ';'; &CMD.; Cmd = "%TEST1(DATA=&LIBREF.." !! trim(MemName) !! ');'; &CMD.; Cmd = "%TEST1(DATA=&LIBREF.." !! trim(MemName) !! ",COND=1);'; &CMD.; %*do until(EndoFile);end; stop; run; %*NOTE: call execute happens in this step; run;

Ron Fehd the macro maven CDC Atlanta GA USA RJF2@cdc.gov

If you think I know what I'm doing it's probably because you know even less about it. -- Pot-Shots by Ashleigh Brilliant

do not fold, spindle, or mutilate -- IBM punch card ... the call execute argument(s)


Back to: Top of message | Previous page | Main SAS-L page