good perl idiom equivilent to SQL's IN operator

TeeJay on 2005-07-19T15:25:21

This afternoon I was changing some code that checked if a value matched one of a couple of values for each clause, but now it matches up to a dozen.

If it was SQL I'd use the nice IN operator, but perl lacks an equivilent. Will perl6 include a fast, efficient equivilent without resorting to the LISP/Scheme/CrackInspired syntax that I see so much of in the summaries?

Using perl 5 I abuse grep like so

   if (grep ($var == $_ , (3,4,6,8..11,12,14,15))) {
     print " matches\n";
   } else {
     print " has no matches\n"
   }


Which I think is pretty readable if slower than a bunch of hand written == and & glued together across 6 lines.
or I could use the Number::Range module.


List::MoreUtils?

Ovid on 2005-07-19T15:51:38

While I can't say I'm wild about the name -- though I can't think of a better one -- the List::MoreUtils module seems to offer a more general solution.

use List::MoreUtils qw/any/;

if (any {$var == $_ } 3,4,6,8..11,12,14,15) {
    print " matches\n";
} else {
    print " has no matches\n"
}

Re:

Aristotle on 2005-07-20T05:27:46

I don’t see how that makes anything any better. You can s/any/grep/ and remove the use line and that works.

Re:

Ovid on 2005-07-20T07:46:08

Because if you have a large list, grep forces you to iterate over every element. That could be expensive if called many times. any is easy to read and terminates as soon as any element in the list meets the condition. Of course, that still doesn't mean that any is better, but if you're using that in conjunction with other functions in that module, it can be a win.

Re:

Aristotle on 2005-07-20T08:56:37

Well, yes. And I did consider that.

But it really only matters if you have a large list in which you look for some values much more frequently than for others, so reordering the list can yield consistent savings. Otherwise you’re just reducing the runtime from n steps to n/2 averaged steps – both of which are O(n).

If that tiny an optimization actually manages to make a noticable difference, then you really have no excuse not to use a hash.

If the code block was doing something much more complex that can’t be expressed in terms of hash exist/lookup, any would be worth considering, but for a simple ∈ operation, any case too big for grep to handle is also too big for any to handle relative to the better option that is available.

Of course Perl6 will solve your problem

Limbic Region on 2005-07-19T17:00:23

In p5, you could use Quantum::Superpositions any()

In p6, they are called junctions - and in this case it is still any()

Cheers