1

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;
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
aidan
  • 9,310
  • 8
  • 68
  • 82
  • `perl -we 'print "true" if 5 ~~ (1..5)'`, besides `~~` is deprecated as of 5.18. – mpapec Dec 03 '13 at 07:18
  • 2
    `~~` is experimental and subject to change (or possibly removal) at some point in the future. It is *not* "deprecated". – ysth Dec 03 '13 at 07:24
  • This is why you should always `use warnings 'all';`: your first snippet warns "Use of uninitialized value $. in range (or flip)", which should tip you off that something funky is going on. – ThisSuitIsBlackNot Sep 19 '16 at 15:57

1 Answers1

3

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.

hobbs
  • 223,387
  • 19
  • 210
  • 288