Search code examples
perlsmartmatch

Why does smartmatch return a different value when I use the range operator on the righthand side instead of an array?


Why does this smartmatch return false

$value = 5;
print "true" if $value ~~ (1..5);

while this one returns true?

$value = 5;
@match = (1..5);
print "true" if $value ~~ @match;

Solution

  • In the first case, the right side of the ~~ operator is evaluated in scalar context, so the expression 1..5 is the flip-flop operator, becoming true when $. is 1 and becoming false after $. is 5. The true or false value of the flip-flop is then used as the RHS of the smart-match (I believe it will be treated as a numeric 1 or a string "" respectively, but I haven't proven that).

    In the second case, @match receives the values (1, 2, 3, 4, 5), and $value ~~ @match is true if $value is any one of those numbers (but not if, for instance, it's 1.5, even though that's in the range 1..5).

    If what you really want is a range smartmatch, your best bet is to create a range class that takes lower and upper bounds, and provides a ~~ operator overload that returns whether the LHS falls within the range. Then you could (with the appropriate sugar) write if $value ~~ Range(1,5). In fact, that's pretty much the only recommended way to do much of anything with smartmatch. Most of what it does is too magical for practical use.