BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Lee_wan
Obsidian | Level 7

Hi all,

 

Why I run the data B, the log report " Missing values were generated as a result of performing an operation on missing value"

 

But the log of data C is clean.

 

I want to use the data B with the clean log. Thanks. 

data a;
  a="20DEC2019:00:00:00.000"dt;output;
  a=.;output;
  format a DATETIME22.3;
run;

data b;
  set a;
  c=ifc(a ne .,put(datepart(a),date9.),'');
run;

data c;
  set a ;
  if a ne . then c=put(datepart(a),date9.);
  else c='';
run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
ChrisNZ
Tourmaline | Level 20

Sadly, SAS made the decision that the ifx() functions were executed by the compiler like every other function.

This means that all the function parameters are processed all the time.

The consequences of this decision are:

1. Your B code generates a message, as you have observed. There is no doubt that this undermines the usefulness of the function.

2. There is a performance cost as both the true and false parameters are executed, when only one of them is ever needed.

I can't think of a good reason for this decision.

 

 

View solution in original post

9 REPLIES 9
ChrisNZ
Tourmaline | Level 20

Sadly, SAS made the decision that the ifx() functions were executed by the compiler like every other function.

This means that all the function parameters are processed all the time.

The consequences of this decision are:

1. Your B code generates a message, as you have observed. There is no doubt that this undermines the usefulness of the function.

2. There is a performance cost as both the true and false parameters are executed, when only one of them is ever needed.

I can't think of a good reason for this decision.

 

 

Kurt_Bremser
Super User

I even think that this behavior is the explicit purpose of the ifc and ifn functions. Otherwise a simple if-then-else is all that's needed, and we've been coding that since the beginning of non-assembler programming languages.

 

When a function is called, the argument values need to be pushed onto the stack, and the function retrieves them from there. If you do not want this to happen, the data step compiler would need extra coding to recognize the ifc/ifn function and then translate the whole call into a normal if-then-else statement; something that the programmer can easily do on their own, if non-execution of a branch is wanted.

ChrisNZ
Tourmaline | Level 20

@Kurt_Bremser Your explanation makes sense.

I find a code such as

VAR = ifn(&test1, 1
    , ifn(&test2, 2
    , ifn(&test3, 3, 4 )));

much more legible than

if      &test1 then VAR= 1;
else if &test2 then VAR= 2;
else if &test3 then VAR= 3;
else                VAR= 4;

and I often use if() just for this reason. The example given (dealing with missing values) is also a hindrance.

So I wish the compiler behaved as if it found a if then test; I don't think the extra compiler logic to identify this would be of any consequence.

That's just me though. I understand your reasons and they are valid too.

 

 

 

Tom
Super User Tom
Super User

Not sure I see how that is better pattern.  Turning logic into function calls might make sense in something like Excel spreadsheet where everything has to be a function.  If it is just the symmetry you like then use a SELECT statement instead of nested if/then/else. 


@ChrisNZ wrote:

@Kurt_Bremser Your explanation makes sense.

I find a code such as

VAR = ifn(&test1, 1
    , ifn(&test2, 2
    , ifn(&test3, 3, 4 )));

much more legible than

if      &test1 then VAR= 1;
else if &test2 then VAR= 2;
else if &test3 then VAR= 3;
else                VAR= 4;

and I often use if() just for this reason. The example given (dealing with missing values) is also a hindrance.

So I wish the compiler behaved as if it found a if then test; I don't think the extra compiler logic to identify this would be of any consequence.

That's just me though. I understand your reasons and they are valid too.

 

ChrisNZ
Tourmaline | Level 20

I agree that a function is not best suited for this kind of test.

But it is much more legible in this case, imho.

Hence my preference. I put legibility first here.

 

Lee_wan
Obsidian | Level 7
Thanks for your answer!
Patrick
Opal | Level 21

@ChrisNZ described the root cause. For your specific sample code using format dtdate. would allow you to not use function datepart() which throws the note. Using format dtdate. even removes the need for conditional logic.

data a;
  a="20DEC2019:00:00:00.000"dt;output;
  a=.;output;
  format a DATETIME22.3;
run;

data b;
  set a;
  c=put(a, dtdate9.);
/*  c=ifc(a ne .,put(a,dtdate9.),'');*/
run;

 

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 9 replies
  • 1519 views
  • 8 likes
  • 5 in conversation