Date: Thu, 28 Apr 2005 18:27:50 +0000
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Ian Whitlock <iw1junk@COMCAST.NET>
Subject: Re: Problem with Nested Macros
Sa Polo now has his CALL EXECUTE version of code working, but
complained about his current version of %RunMe
> Unfortunately the %if %sysfunc(fexist(srcfile)) statement
> references only the last parameter passed in this
> particular case c:\flags_fiveT1A_20050331.csv.
> It seems to be some sort of macro resolution problem.
The code was
> %MACRO RunMe(xx);
> %PUT xx=&xx;
> FILENAME srcfile "c:\&xx";
> %if %sysfunc(fexist(srcfile)) %then
> %put The file identified by the fileref srcfile exists.;
> %put %sysfunc(sysmsg());
to be called in a DATA step by
> CALL EXECUTE( '%RunMe('||yy||')');
In response Dennis suggested
dd> Yes there are some complexities in timing when using CALL
dd> EXECUTE. I pefer to keep things simple, Change your runme
dd> macro to only run cacro code: (use FILEEXIST instead of
dd> %MACRO RunMe(xx);
dd> %PUT xx=&xx;
dd> %if %sysfunc(fileexist(c:\&xx)) %then
dd> %put The file identified by the fileref srcfile exists.;
dd> %put %sysfunc(sysmsg());
Perhaps it is worth pointing out what happened. In both cases
the macro was executed immediately during execution of the DATA
step, i.e. any SAS code to be generated was generated.
In Dennis' case all the code is macro instructions and all were
executed in sequence as expected.
In Sa's case, the macro code is executed at once, but the SAS code
is passed to the input stack for later execution. In other words,
all the FILENAME statements were executed after the step finished
while all the macro code applying the fileref, SRCFILE, was applied
before the relevant FILENAME statements were made. Why did Sa think
it was the last file that was used? He must have tested interactively,
created the filerefs and then tested again for some reason. At this
point SRCFILE is pointing at the last file so that is the file whose
existence is being tested.
Whether Dennis' fix is good enough or not depends on whether Sa is
finished writing %RunMe or not, and if not what the future code
looks like. To cover future complications Sa may want to enhance the
CALL EXECUTE to
CALL EXECUTE( '%nrstr(%RunMe('||yy||'))');
In this case the macro is not invoked during execution of the
DATA step, but afterward when there are no mysterious timing
complexities or mysterious macro resolution problems.
I have often wondered why, when SI was adding so many new
functions to version 9, they did not also add a CALL NRexecute
routine to cover these problems. The biggest benefit might have
been in the documentation explaining the difference between CALL
EXECUTE and CALL NRexecute.