Qiang Li
Qiang Li

Reputation: 10855

Why does @array ~~ LIST return false even though @array contains the same elements as LIST?

I have

@a = (1,2,3); print (@a ~~ (1,2,3))

and

@a = (1,2,3); print (@a == (1,2,3))

The first one is the one I expect to work, but it does not print anything. The second one does print 1.

Why? Isn't the smart matching operator ~~ supposed to match in the case of @a ~~ (1,2,3)?

Upvotes: 4

Views: 1251

Answers (3)

brian d foy
brian d foy

Reputation: 132812

Start with What is the difference between a list and an array? in the perlfaq. It specifically shows you how your choice of values is wrong.

You might also start by writing out why you expected each to work or not work, so that we might correct your expectations. Why did you think you'd get the results that you expected?

As for the smart match bits, there's no rule for ARRAY ~~ LIST. The smart match only works with the pairs enumerated in its table in perlsyn. It's going to force it to be one of those pairs.

When you run into these problems, try many more cases:

#!perl
use v5.10.1;
use strict;
use warnings;

my @a = (1,2,3);
say "\@a is @a";
say "\@a ~~ (1,2,3) is ", try( @a ~~ (1,2,3) );
say "\@a ~~ [1,2,3] is ", try( @a ~~ [1,2,3] );
say "\@a ~~ 3 is ", try( @a ~~ 3 );
say "3 ~~ \@a is ", try( 3 ~~ @a );

say '';

my @b = (4,5,6);
say "\@b is @b";
say "\@b ~~ (4,5,6) is ", try( @b ~~ (4,5,6) );
say "\@b ~~ [4,5,6] is ", try( @b ~~ [4,5,6] );
say "\@b ~~ 3 is ", try( @b ~~ 3 );
say "3 ~~ \@b is ", try( 3 ~~ @b );

say '';
say "\@b ~~ \@a is ", try( @b ~~ @a );

sub try { $_[0] || 0 }

The output of the various cases is the clue that you misread the docs:

Useless use of a constant (2) in void context at test.pl line 8.
Useless use of a constant (4) in void context at test.pl line 17.
Useless use of a constant (5) in void context at test.pl line 17.
@a is 1 2 3
@a ~~ (1,2,3) is 0
@a ~~ [1,2,3] is 1
@a ~~ 3 is 0
3 ~~ @a is 1

@b is 4 5 6
@b ~~ (4,5,6) is 0
@b ~~ [4,5,6] is 1
@b ~~ 3 is 0
3 ~~ @b is 0

@b ~~ @a is 0

Upvotes: 6

ikegami
ikegami

Reputation: 385887

For a second, lets consider the slightly different

\@a ~~ (1,2,3)

~~ evaluates its arguments in scalar context, so the above is the same as

scalar(\@a) ~~ scalar(1,2,3)
  • \@a (in any context) returns a reference to @a.
  • 1, 2, 3 in scalar context is similar to do { 1; 2; 3 }, returning 3.

So minus a couple of warnings*, the above is equivalent to

\@a ~~ 3

What you actually want is

\@a ~~ do { my @temp = (1,2,3); \@temp }

which can be shortened to

\@a ~~ [ 1,2,3 ]

Finally, the magic of ~~ allows \@a to be written as @a, so that can be shortened further to

@a ~~ [ 1,2,3 ]

* — Always use use strict; use warnings;!

Upvotes: 12

Jim Davis
Jim Davis

Reputation: 5290

Smart match tries to do what I think you're expecting if you use an array or an array reference on the right side -- but not a list.

$ perl -E '@a = (1, 2, 3); say (@a ~~ (1, 2, 3))'

$ perl -E '@a = (1, 2, 3); say ((1, 2, 3) ~~ @a)' # also misguided, but different
1
$ perl -E '@a = (1, 2, 3); say (@a ~~ [1, 2, 3])'
1

Upvotes: 9

Related Questions