Hi SASsy People! 😉 Counting on that your "sassyness" will help me.
Inspired by discussion with Quentin ( @Quentin sorry for pulling you into this 😄 )
I was working on new extension to my BasePlus package and encountered this "interesting" situation.
The idea was to concoct "lazy typer"/"syntactic sugar" macro name %IFFUN() which would allow for something like:
%let test = %iffunc((<condition>),value when TRUE,value when FALSE);
(I know about the "%sysfunc(ifc(c,t,f,))" combo, that's not the point here.)
I wanted to provide the conditions like:
1) (&x.=1)
2) (9.9<&y)
3) (TRUE=true)
4) (1/3 = &z. * 0.5)
5) (1=1.0)
6) (%scan(&t.,1)=A)
etc.
and of course something like
7) (&n. IN (1 3 5))
too.
Internally I'm using the %SYSEVALF() to evaluate expressions and everything was going well until the point 7).
It looks like the %SYSEVALF() macrofunction and the IN operator don't like each other...
Lets look at those 3 macros:
%macro test1()/minoperator;
%if 1.1 IN (1.1 2.1 3.1) %then %put [&sysmacroname.] 123!!;
%mend;
%macro test2()/minoperator;
%if %eval(1.1 IN (1.1 2.1 3.1)) %then %put [&sysmacroname.] 123!!;
%mend;
%macro test3()/minoperator;
%if %sysevalf(1.1 IN (1.1 2.1 3.1)) %then %put [&sysmacroname.] 123!!;
%mend;
What would you expect to see in the log after running:
%test1()
%test2()
%test3()
??
Would it be:
1 %test1() [TEST1] 123!! 2 %test2() [TEST2] 123!! 3 %test3() [TEST3] 123!!
??
Well, if yes, you would be surprised.
The log is:
1 %test1() [TEST1] 123!! 2 %test2() [TEST2] 123!! 3 %test3() ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: (1.1 IN (1.1 2.1 3.1)) ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition. ERROR: The macro TEST3 will stop executing.
To my surprise, the error is not in "plain" %IF-%THEN, not in %EVAL(), but it blows-up in the %SYSEVALF() which seems to be "the most robust one"...
Before writing here I went through:
1)
https://support.sas.com/en/books/authors/art-carpenter.html
both:
"Carpenter's Complete Guide to the SAS Macro Language, Third Edition"
and
"Carpenter’s Guide to Innovative SAS Techniques"
2)
https://support.sas.com/en/books/authors/robert-virgile.html
"SAS Macro Language Magic: Discovering Advanced Techniques"
3)
https://blogs.sas.com/content/author/micheleburlew/
"SAS Macro Programming Made Easy, Third Edition"
but didn't find anything related to or describing the subject.
Also 9.4 documentation pages:
- sysevalf - https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/p1d9ypna2tpt16n1xam57kuffcpt.htm
- minoperator - https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/p0pbehl7wj5sl4n1ov1ortnehtba.htm
- mindelimiter= - https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n0vc5y2nyi55dvn1agla9j658kwh.htm
- macro expressions - https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n00ks71pt5pjtfn1g939tuoptql4.htm (all four sub-sections too)
- macro error messages - https://documentation.sas.com/doc/en/mcrolref/1.0/n1mcxptbxr3qhwn1q6swv33z8akq.htm
don't provide any "warnings", "notes", or "attentions" to the subject.
And it's not onlu 9.4... the same is for Viya doc too https://documentation.sas.com/doc/en/mcrolref/1.0/p14qac7nd7n0s1n1rfte5bwrpfcy.htm
My questions to you are:
0) Is it "well known" behaviour and it's just me who didn't smashed head on it yet?
1) Did you encounter any place where the behaviour is documented (sas note)?
2) Do you consider such behaviour a bug worth mentioning to SAS support?
I'm intentionally mentioning some of you in the post's comments hoping for your thoughts, insights, and, hopefully, some "good-old SAS-L" type discussion.
All the best
Bart
I got information form SAS Tech. Support that R&D did not decide to fix the error.
They decided to update the documentation with something like: "The %SYSEVALF function does not support the IN logical operator in expression."
The updated doc. should be available within a month.
Bart
---
@Tom @PaigeMiller @Ksharp @SASKiwi @ChrisNZ @RichardDeVen @data_null__
---
@Kurt_Bremser @FreelanceReinh @Reeza @Patrick @DonH @hashman @Rick_SAS @mkeintz @sasbrah
I tend to use the %INM macro rather than the IN operator
%macro inm(slist,s);
/* SAS Macro %inm to see if &s is contained in a string or list &slist */
/* Borrowed from https://groups.google.com/forum/#!topic/comp.soft-sys.sas/fWcSDgg11tE */
%if %sysfunc(indexw(&slist,&s)) gt 0 %then 1 ;
%else 0;
%mend;
What happens if you do
%if %sysevalf(1 IN (1 2 3))
?
(I'm on my tablet, so no SODA available)
This:
%macro test4()/minoperator;
%if %sysevalf(1 IN (1 2 3)) %then %put [&sysmacroname.] 123!!;
%mend;
%macro test5()/minoperator;
%if %sysevalf(A IN (A B C)) %then %put [&sysmacroname.] 123!!;
%mend;
%test4()
%test5()
gives:
1 %test4() ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 1 IN (1 2 3) ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition. ERROR: The macro TEST4 will stop executing. 2 %test5() ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: A IN (A B C) ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition. ERROR: The macro TEST5 will stop executing.
Bart
So it's clear that it is not the data or type of data which causes this, SYSEVALF does not like the IN operator at all. This is either a bug or not properly documented.
Since %IF can be used without a macro, I suggest to run the tests in "open code" with OPTIONS MINOPERATOR set. Maybe the log can give us additional clues.
Have you enabled the Macro In Operator (MINOPERATOR) option?
When SAS initially enabled the IN operator for the Macro language they got feedback from lots of customers that it broke their code (I can't recall the details, but I know that was the reason). So SAS added an option to enable that.
Apologies if that was mentioned earlier - based on a quick scan I did not see that mentioned.
@yabwon 's macro definitions have the /MINOPERATOR option, and %EVAL works there. It's only %SYSEVALF which coughs up.
Hi Don,
Yes, I tried with both:
options minoperator;
and
%macro ... / minoperator;
directly in macro definition.
But it didn't change a thing.
Bart
Open code version:
options minoperator;
%if %sysevalf(1 IN (1 2 3)) %then
%do;
%put [Open Code] 123!!;
%end;
produces:
1 options minoperator;
2 %if %sysevalf(1 IN (1 2 3)) %then
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 1 IN (1 2 3)
ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition.
ERROR: Skipping to next %END statement.
3 %do;
4 %put [Open Code] 123!!;
5 %end;
Basically, nothing new.
Bart
Just wanted to make sure there is no difference between the MINOPERATOR option of %MACRO and the system option.
Since it is not documented for the %SYSEVALF function, IMO this is a bug.
Yes, nothing worth mentioning:
1 options mlogic mprint symbolgen;
2 %test5()
MLOGIC(TEST5): Beginning execution.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: A IN (A B C)
ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition.
ERROR: The macro TEST5 will stop executing.
MLOGIC(TEST5): Ending execution.
(based on one of earlier examples)
Hi @yabwon,
Using a simplified version of the macro (with Windows SAS 9.4M5) SAS itself admits that there is a bug:
1 %macro test / minoperator; 2 %if %sysevalf(1 IN 1) %then %put OK; 3 %mend; 4 5 %test ERROR: A bug in SAS has been encountered. Please call your SAS representative and report the following message: YJEVAL: Invalid arithmetic operator 26 encountered. ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition. ERROR: The macro TEST will stop executing.
The first two lines of the error messages (what is YJEVAL, btw? And arithmetic operator 26?) are also written to the output window (in red color).
(Same with condition 1 IN (1).)
Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.
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.
Ready to level-up your skills? Choose your own adventure.