Take a look on code below:
proc fcmp outlib=WORK.MYFUNC.tmp;
function calcval(var1, var2,var3, var4);
options cmplib=(work.myfunc) ;
proc fcmp outlib=work.myfunc.tmp;
Function is created to get minimum of 3 variables and multiply with fourth variable. As you can see that CNT3 and CNT4 variables are not defined in test dataset, but used in function.
The program is not giving variable uninitialized note and CNT3 and CNT4 are not added in final test dataset.
Instead of user-defined function, if I use any SAS default function, it will give the variable uninitialized note and also add these two variables to test dataset.
I prefer user-defined function should also work similar to sas default functions.
The "variable uninitialized" note is imho important as it often indicates that something is wrong with the code even though it's syntactically correct.
So like Bhavin I would like that variables passed as parameters to a user defined function behave exactly the same like variables passed as parameters to a SAS supplied function.
What Bhavin in his code demonstrates is, that this is not the case. If one uses a variable only within the user defined function the nothing in the log shows that this variable hasn't been initialized. The variable also doesn't get added to the output data set (as it would if used in exactly the same way in a SAS function).
It looks to me as if the compiler simply ignores variables used within user functions.
I believe in the approach:
a/ Design b/ document c / Build
d/ Test (Evaluate risk) e/ deploy
This as for good programming habits with no "bad coding". This is part of software architecture and engineering. We know the basic SAS language is based on: http://en.wikipedia.org/wiki/Lazy_evaluation as you do not need to define all kind of properties before using them. This is different in more strict languages like ADA see: http://en.wikipedia.org/wiki/Strong_and_weak_typing
There is lot to be found on professional coding and the possible failures
In the toplist of those software error you see all that are caused that the reciever does not validate his input and is just trusting his caller/Messenger.
By this the builder of a subroutine having all repsonsibilities to achieve this should have enough tools and information to achieve this
For this I would like to see better documented examples how to do it.
It's mentioned in FCMP documentation that the variables created within FCMP procedure are local to the function only.
Suppose the function DUR is created to find the duration.
For Adverse event duration calculation, two variables need to be used ASTDT (AE start date) and AENDT (AE end date),
Function call should be like, AEDUR=dur (ASTDT, AENDT).
Suppose the developer has misspelled AENDT and wrote AEENDT in function. The new variable AEENDT will be local to function and will not give uninitialization note. AEDUR variable will have all values missing.
Now, the question is how to do defensive programming in this case to get any programmer defined NOTE in log that input variable to function is not correctly passed.
This has nothing to do with proc fcmp and everything to do with the data step compiler.
There is no reason it should treat user-defined function differently than sas function when it comes to flagging (or creating!) missing variables.
Yes vote for me. This looks like a bug actually, unless SAS can explain why the data step is asked to use a varaible called CNT4 and it doesn't.
Chris, Your assumption is that all the parameters must be data-step variables. Did you verify that assumption?
As with other sas-functions that does not need to be that way. It can be constants or other ones. How to differentiate that? That is the designer builder of the functions job to do.
Jaap, I don't understand your question. In the OP, CNT4 is a function parameter. How can it not be a data step variable?
In the example given, the data step compiler's behaviour is inconsistent with expected behaviour. That's what matters here.
I haven't looked at putting values as parameters instead of variable names to see what happens as that's besides the point raised.
proc fcmp is NOT part of a datastep it is decicated Proc. Base SAS(R) 9.4 Procedures Guide, Third Edition. What you can do with that is creating a function to be used somewhere in SAS (not necessary a datastep)
SAS(R) 9.4 Functions and CALL Routines: Reference, Third Edition (these are the functions you should know as standard deliverd by SAS). Impossible to know them all.
An interesting one is: SAS(R) 9.4 Functions and CALL Routines: Reference, Third Edition (call module) Just think about what that one can do.
Base SAS(R) 9.4 Procedures Guide, Third Edition (Concepts: FCMP Procedure) in the example you are seeing the second parm is just a string day_date not a datastep var.
the doc says it follows the data-step syntax, but it is not a datastep as there is no PDV active.
Look at the FCMP samples they are really consistent accepting thing like an array or almost anything. No surely not datastep vars only.
It is the FCMP documentation to be known.
I still don't know what point you are trying to make Jaap.
What does the fact that functions can accept different types of parameters has anything to do with data step compilation?
Back to the behaviour shown.
CNT4 is a datastep variable isn't it? If not I'd be curious to know what you think it is?
Why would it be a DS variable in: data; A=sum(CNT4); run; and not in data; A=my_func(CNT4);run; ?
If it is a DS variable, why isn't a PDV entry created for it? This is the unexpected behaviour.
It looks like the data step compiler ignores arguments of user-defined functions when creating PDV entries.
And I reckon that's wrong since that not expected compilation behaviour.
Now if SAS can't be bothered to fix this unexpected behaviour, or if they provide a reason for it, at least an Usage Note should be written to document it.
Even better would be to fix this inconsistency.
This suggestion belongs to tech support really, so they can raise a defect.
Note: not knowing what variable type is wanted is not a reason. Variables are always created numeric by default, as in: data; X=A||B; run;
Note2: The only documented case where the compiler is oblivious of variables used is for DS objects like the hash object. We are not using objects here.
When creating a function in FCMP that is meant to receive a flexible number of arguments, the VARARGS option would be a more 'supported' method to achieve it. As for the problem at hand, it's easiest to just accept the idea that arguments in user-defined functions are not examined by the compiler for matching names. It can be viewed as a useful feature for creating functions in the style of the OP, where a parameter is 'optional' but something still must be passed to it anyway. Kind of a kludge. There are many improvements that can be made to FCMP.
proc fcmp outlib=work.func.math;
function multmin(m, var
do i=2 to dim(var);
if ^missing(var) and min>var then min=var;
array x _temporary_ (10 2 2*.);
array y _temporary_ (9*100 1);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.