3

According to Programming Perl, using smartmatch with "any" on the left and a number on the right checks numeric equality:

------------------------------------------------------------------------------
| Left | Right |    Description    | Like (But Evaluated in Boolean Context) |
------------------------------------------------------------------------------
|  Any |   Num |  Numeric equality |               Any == Num                |

Therefore, I expect the following to output 1:

my @arr = ('aaa');
my $num = 1;
say @arr ~~ $num;

but it actually outputs the empty string.

I thought @arr would be converted to scalar 1 because it has 1 element, so say @arr ~~ $num would be equivalent to say @arr == $num.

Why is @arr ~~ $num different from @arr == $num?

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
d.k
  • 4,234
  • 2
  • 26
  • 38

2 Answers2

3

The smartmatch operator obviously doesn't take lists as operands. As such, it evaluates its operands in scalar context. If that was the end of the story, the following wouldn't work

my @a = ('aaa', 'bbb');
my $s = 'aaa';
say $s ~~ @a;

because it would be the same as

say 'aaa' ~~ 2;

But it's clear that it does work. That's because smartmatch automatically creates a reference to its operands that are arrays or hashes, just like push does to its first operand. That means

say $s ~~ @a;

is really

say $s ~~ \@a;

and (your code)

say @a ~~ $n;

is the same as

say \@a == $n;

You need to get the length explicitly. The following will do what you want:

say 0+@a ~~ $n;

Of course, so would

say 0+@a == $n;

or even

say @a == $n;
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thanks to that answer, I spotted the note `The "Like" column is not always an exact rendition`. So it should not be treated as exactly equal alternative – d.k Jul 28 '12 at 15:21
2

That's because smartmatch takes a reference first. @array ~~ $num would be equivalent to \@array == $num, which obviously is very very unlikely to be true.

You might want to use my Smart::Match module and do @array ~~ array_length($num), @array ~~ contains($num) and other things in a non-surprising way.

Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
  • From "Programming Perl": `The smartmatch implicitly dereferences any nonblessed hash or array reference, so the HASH and ARRAY entries apply in those cases`. So it seems that smartmatching must be done on array, not reference, isn't it? – d.k Jul 28 '12 at 12:00
  • @caligula: Then "Programming Perl" is subtly confusing. You can blame me a little for that, I was one of the proofreaders… – Leon Timmermans Jul 30 '12 at 19:40