Alias include? with match operator

commentary

Mon Sep 21 10:48:49 -0700 2009

Often I need to test some variable against 2 or 3 values. The standard way to do it in most languages is:

This can get ugly if you start using more than 2 conditions (even if it is still a small number such as 3 or 4). Also sometimes your variable is not a variable but a chain of method calls that you don’t want to evaluate every time. For example:

Now you might just create a temp variable to shorten up the variable name and to avoid the multiple evaluations. But it still does not seem elegant. It still feels verbose and the temp variable while useful adds to the ugliness. So a common solution I have been using is:

This is much shorter and doesn’t involve multiple evalutations. So overall I like it. But I have never felt it read right. include? implies a large list of items. It make sense to say list.include?. But if list is just 2 or 3 items and they are literals it doesn’t read right. I feel like it should read the other way and not use the word include. Something that reads closer to “controller.action_name.humanize is equal to Edit, New or Show”.

So my new solution is to use the match operator. So I now say:

I can put the variable and the list on either side of the equation (whatever reads right). It seems to have the right semantics as the match operator is looking to see if the item we are comparing it to somehow matches. It not looking for equality but just some sort of similarity. Also we can use !~ and it work how we would expect.

So how do we make the match operator actually work like this? For the most part we just alias =~ to include? on the Enumerable object and strings will work automatically since the string implements =~ to call =~ on the other object is the other object is not a regexp. But to make it work on all objects (numbers, etc.) we can just define a similar method on Object.

Here is my final implementation including unit tests:

Am I overloading the match operator too much? Does the read better and produce more elegant code to you? Or should I stick with the standard include? method?

NOTE: I tried using === instead of =~ as this would allow me to use it in a case statement. Also it would match how Range already does it. But I ended up with too many complications so I decided the =~ operator has similar meaning and doesn’t carry the problems with it.

blog comments powered by Disqus