Date: Sat, 5 Jul 2008 00:33:53 +0000
Reply-To: iw1junk@COMCAST.NET
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Ian Whitlock <iw1junk@COMCAST.NET>
Subject: Re: Macro behavior in IML and DATA step
Sumary: Theory can be wrong, but sometimes appear to explain.
#iw-value=1
Paul,
You wrote, "The macro system behaves a little differently in IML than
it does in other parts of SAS."
You have things the wrong way around. It is the procedure or language
that behaves differently, not macro. It is sort like having a theory
that the cart pushes the horse rather than the horse pulls the cart.
Given the appropriate environment, a macro variable is always
available immediately following EXECUTION of the statement that
assigns the variable. Since in some languages of the SAS family
statements do not execute until a whole step is compiled, we find some
languages where a variable created by a statement S is not available
to the compiler by a statement following S because S does not EXECUTE
until the step has finished compiling, i.e. long after the compiler
needs the new value of the macro variable. And we find some languages
where the variable is available in a subsequent statement to the
compiler because each statement is executed immediately upon
compilation.
Let's look at a modified form of your first example.
291 %let _i=1;
292 data _null_;
293 call symput("_i",'2');
294 call execute ('%put "&_i";') ;
295 run;
"2"
NOTE: DATA statement used (Total process time):
real time 0.07 seconds
cpu time 0.01 seconds
NOTE: CALL EXECUTE routine executed successfully, but no SAS
statements were generated.
What is the difference between your example and mine? Mine does not
ask the compiler to know the value of _I, yours does.
The more accurate statement is that some compiled languages behave
differently during compilation, not that the macro facility behaves
differently. So why is it important? With your statement one might
look to the macro documentation to find out what is happening, while
with mine one would look in the language or procedure documentation to
understand what is happening. Moreover, one would be on the lookout
for different compile/execute behavior in other procedure with my
phrasing, but not yours. Your statement also leads one to believe
that he has to learn different macro languages rather than different
procedure behavior. In short it may work for you, but it is
misleading to one who wants to understand in general what to expect.
Now let's look at another language where each statement executes after
it is compiled, as opposed to when the procedure is finished.
296 data w ;
297 x = 1 ;
298 run ;
NOTE: The data set WORK.W has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.06 seconds
cpu time 0.01 seconds
299
300 %let works = 1 ;
301 proc sql ;
302 select "hello world" into :works from w ;
303 %put &works ;
hello world
304 quit ;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.20 seconds
cpu time 0.02 seconds
If you know that in both IML and SQL that statements execute
immediately upon compilation then my second example is no surprise.
But if you think that macro behaves differently in IML then you will
have to learn the same thing all over about SQL as part of the price
paid for hanging on to a wrong theory.
Ian Whitlock
==============
Date: Fri, 4 Jul 2008 14:14:32 -0500
Reply-To: paul@WUBIOS.WUSTL.EDU
Sender: "SAS(r) Discussion"
From: Paul Thompson <paul@WUBIOS.WUSTL.EDU>
Subject: Macro behavior in IML and DATA step
Content-Type: text/plain; charset=ISO-8859-1; DelSp="Yes";
format="flowed"
The macro system behaves a little differently in IML than it does in
other parts of SAS. In IML, each statement is executed immediately,
rather than waiting until all code is assembled. This is a bit odd
for those who use macros outside of IML.
Here is a simple example. First, we see the normal behavior in the
datastep, where the call symput does not affect the value of _i until
after the run:
75 options mprint;
76
77 %let _i=1;
78 data _null_;
79 call symput("_i",'2');
80 put "&_i";
81 run;
1
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
82 %put _i[&_i];
_i[2]
This is all quite what SAS users expect.
In IML, things behave a little differently. Here is a comparable
example, with the output brought in from the OUTPUT window shown
below.
83
84 %let _i=1;
85 proc iml;
NOTE: IML Ready
86 call symput("_i",'2');
87 print "Current value of _i: &_i";
88 quit;
NOTE: Exiting IML.
NOTE: PROCEDURE IML used (Total process time):
real time 0.03 seconds
cpu time 0.01 seconds
89 %put _i[&_i];
_i[2]
From the OUTPUT window:
The SAS System 13:58 Friday,
July 4, 2008 6
Current value of _i: 2
I encourage those who have not tried this to do so.
IML is an interesting part of SAS. Its immediate execution component
is very useful. It gives the ability of macro code to more tightly
self-modify.
This issue was raised by a post or two earlier today. I thought it
interesting, so present this small tutorial.