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

 

I have a macro which needs to validate keyword parameters against a list. The code below distills the issue (the actual macro is much more complex).

 

 

%MACRO CONVERTOR (CONVERSION_TYPE = );

  %IF &CONVERSION_TYPE IN (MILES_TO_METERS,MILES_TO_FEET) %THEN %DO;
    %LET ORIGINAL_UNIT = MILES;
	                                                       %END;

%MEND;

%CONVERTOR (CONVERSION_TYPE = MILES_TO_METERS);

Executing this yields the following error in the log:

 

ERROR: Required operator not found in expression: &CONVERSION IN       (MILES_TO_METERS,MILES_TO_FEET)

 

Could someone please point out the correct way to do this? It seems that SAS doesn't allow the IN operator within a macro code?

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Trying to us IN as an operator in macro code is tricky, and probably not worth it.  If you do want to use it then make sure to tell the macro compiler that you want to use it and what character to use as the delimiter. It is generally a bad idea to use a comma as a delimiter in macro code as it can cause trouble when trying to pass values into macro functions (or macro calls) since comma is used as the delimiter between arguments (parameters).

%macro convertor(conversion_type) / minoperator mindelimiter='|';
%local original_unit ;
%if &conversion_type in miles_to_meters|miles_to_feet %then %do;
  %let original_unit = %scan(&conversion_type,1,_);
%end;
%else %put WARNING: Conversion_type not recognized. &=conversion_type;
%put &=conversion_type &=original_unit ;
%mend;

%convertor(conversion_type = miles_to_meters);
%convertor(conversion_type = pounds_to_dollars);

 

 

View solution in original post

6 REPLIES 6
novinosrin
Tourmaline | Level 20

Try using

 *macro IN operator;
  options minoperator mindelimiter=',';

specify the correct delimiter  

Reeza
Super User

Historically IN was not a macro operation, but it was added at some point in the last decade. For backward compatibility the old functionality remains and you have to specify the options. I think you may also need a space between the words? Or at least it helps to make it legible and easier to debug. 

 

I find it easiest to 

1) Set options permanently as suggested by @novinosrin

2) Set it specifically for each macro to avoid unexpected behaviour. 

 

I also like to add an %ELSE and %PUT to my tests to make it clear where my logic is failing.

 

%MACRO CONVERTOR (CONVERSION_TYPE = ) / minoperator mindelimiter=',';

  %IF &CONVERSION_TYPE IN (MILES_TO_METERS, MILES_TO_FEET) %THEN %DO;
    %PUT ORIGINAL_UNIT = MILES;
	                                                       %END;
   %ELSE %PUT Logic failed;

%MEND;

%CONVERTOR (CONVERSION_TYPE = MILES_TO_METERS);

 

Astounding
PROC Star

In addition to specifying the two options ...

 

Off the top of my head and untested ...

 

Do NOT use parentheses around the list of values.

 

Do NOT add a space on either side of the delimiter.

Tom
Super User Tom
Super User

Trying to us IN as an operator in macro code is tricky, and probably not worth it.  If you do want to use it then make sure to tell the macro compiler that you want to use it and what character to use as the delimiter. It is generally a bad idea to use a comma as a delimiter in macro code as it can cause trouble when trying to pass values into macro functions (or macro calls) since comma is used as the delimiter between arguments (parameters).

%macro convertor(conversion_type) / minoperator mindelimiter='|';
%local original_unit ;
%if &conversion_type in miles_to_meters|miles_to_feet %then %do;
  %let original_unit = %scan(&conversion_type,1,_);
%end;
%else %put WARNING: Conversion_type not recognized. &=conversion_type;
%put &=conversion_type &=original_unit ;
%mend;

%convertor(conversion_type = miles_to_meters);
%convertor(conversion_type = pounds_to_dollars);

 

 

ScottBass
Rhodochrosite | Level 12

See if https://github.com/scottbass/SAS/blob/master/Macro/parmv.sas meets your needs. 

 

Or, if not, perhaps you can use it as a starting point for your own generic macro parameter validation macro.


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.
desertsp
Obsidian | Level 7

Thank you all for responding.

 

In light of the added complexity, I'll just use the OR operator ....but it's good to know how properly use the IN() operator if needed in the future! A requirement of this particular macro is maintainability by "non SAS experts" hence it would be inappropriate to rely on options or other such dependencies.

 

 

%MACRO CONVERTOR (CONVERSION_TYPE = );

  %IF &CONVERSION_TYPE = MILES_TO_METERS  OR  &CONVERSION_TYPE = MILES_TO_FEET  %THEN %DO;
    %LET ORIGINAL_UNIT = MILES;
	                                                       %END;

%MEND;

%CONVERTOR (CONVERSION_TYPE = MILES_TO_METERS);

 

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 878 views
  • 6 likes
  • 6 in conversation