|
GuyA,
It is not an either-or question. One just needs to select a tool one needs,
and there is nothing specific about IFN/C that would violate this rule. You
could fall prey all the same if you coded
if missing(fields) then incomplete_data2 = 1 ;
else incomplete_data2 = . ;
for in this case, too, the assigned value would be overwritten by 1 or . every time the next array element is encountered, and the result of *this*
IF-THEN-ELSE is no different from dataifn(missing(fields),1,.). You just
need to align your programming logic with your goal.
My beef with IFN is different. I had fancied that one of big advantages of
IFN would be the ability to recode, for instance,
if nmiss (a) or not b then c = . ;
else c = a / b ;
as
c = IFN (nmiss (a) or not b, . , a / b) ;
The intent here is of course to avoid "Missing values were generated..."
and "Division by zero detected..." notes in the log, which I intensely
dislike and never, ever consider a program finished before those have been
completely eradicated. The division by zero is especially vicious since it
is a performance hog.
So, I had thought IFN would be at least as smart as if-then-else is to
never even attempt to execute a/b if the first argument is true: it would
merely assign c=., as prescribed by the second argument and that would be
the end of it.
But no. IFN executes a/b regardless of how the first argument is evaluated,
and of course generates a "missing" note if A and/or B is null and
"division by 0" note if A is not null and B=0. In other words, the
underlying code logic is equivalent to
temp = a/b ;
if nmiss (a) or not b then c = . ;
else c = temp ;
Which begs the question "why?". Note that it does not follow from the SAS
documentation that IFN is anything but equivalent to the corresponding if-
then-else and even give an example supporting the identity. Nowhere in the
documentation the (significant) distinction noted above is mentioned.
I suspect that this is a semi-bug. Since in the absence of the fourth
argument, the first argument can be only either true or false, there is
never a reason to evaluate argument-3 expression if argument-1 is true or
argument-2 expression if argument-1 is false. The reason I have halved the
bug is that, after all, IFN returns a correct result, albeit doing more
(essentially harmful) work than needed.
I cannot determine directly whether IFC also evaluates all 2 (or 3) result-
arguments no matter what argument-1 evaluates to, for due to its character
nature, it does not (thanks goodness!) produce extra junk in the log.
However, it is easy to find indirectly that this is the case:
190 data _null_ ;
191 length a $ 1000 b $ 2000 d $ 3200 ;
192 a = repeat ("0123456789", 99) ;
193 b = repeat ("ABCDEFGHIJ", 199) ;
194 c = "This is a test" ;
195 do i = 1 to 1e6 ;
196 do cond = 1, 0, . ;
197 d = ifc (cond, a || b, b || c, a || c) ;
198 end ;
199 end ;
200 run ;
NOTE: DATA statement used (Total process time):
real time 19.46 seconds
cpu time 12.87 seconds
201
202 data _null_ ;
203 length a $ 1000 b $ 2000 d $ 3200 ;
204 a = repeat ("0123456789", 99) ;
205 b = repeat ("ABCDEFGHIJ", 199) ;
206 c = "This is a test" ;
207 do i = 1 to 1e6 ;
208 do cond = 0, 1, . ;
209 if cond = 1 then d = a || b ;
210 else if cond = 0 then d = b || c ;
211 else if cond = . then d = a || c ;
212 end ;
213 end ;
214 run ;
NOTE: DATA statement used (Total process time):
real time 4.25 seconds
cpu time 3.14 seconds
In light of the 4:1 run-time ratio, methinks evidence is pretty strong...
so if one is programming not only for brevity and beauty but also for
machine performance (when it matters) and/or need to avoid the nasty SAS
log notes one has *programmed* to avoid, it is better to stay away from
IFN/IFC... till the semi-bug is fixed.
Kind regards
------------
Paul Dorfman
Jax, FL
------------
On Fri, 16 Jan 2009 01:09:42 -0800, GuyA <guya.carpenter@GMAIL.COM> wrote:
>Thanks all, that was useful. I will be more careful when using IFN and
>IFC in future, and may just stick to good old IF THEN ELSE syntax!
|