8

The following script smart-matches slices of two arrays. At the start, both arrays are the same and I'm getting reasonable results. Then I change one of the arrays and smart-match two new slices, but it still says that the slices are identical. However, when I copy the slices into arrays, smart-matching the arrays shows that they are indeed different.

The script:

#!/usr/bin/perl
use warnings;
use strict;
use diagnostics;

my @x = qw (one two);
my @y = qw (one two);
my @x_s;
my @y_s;

print "Before change: values are the same:\n";
@x_s = @x[0,1];
@y_s = @y[0,1];
print "\@x_s: @x_s\n";
print +(@x[0,1] ~~ @y[0,1]) ? "equal\n" : "not equal\n";
print +(@x_s ~~ @y_s) ? "equal\n" : "not equal\n";

$x[0]='three';

print "After change: values should be different:\n";
@x_s = @x[0,1];
@y_s = @y[0,1];
print "\@x_s: @x_s\n";
print +(@x[0,1] ~~ @y[0,1]) ? "equal\n" : "not equal\n";
print +(@x_s ~~ @y_s) ? "equal\n" : "not equal\n";

The output:

Before change: values are the same:
@x_s: one two
equal
equal
After change: values should be different:
@x_s: three two
equal
not equal

I'm using Perl 5.10.1, and this happens for both array slices and hash slices. Why does this happen?

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
askucins
  • 93
  • 7
  • 1
    Which version of Perl are you using? With `v5.14.2` I get `equal`, `equal` and `not equal`, `not equal`. – flesk Feb 07 '12 at 12:46

3 Answers3

5

Looks like smart matching works in scalar context with slices.

Consider the following code pieces:

Your case:

#!/usr/bin/perl

my @foo = (1,2);
my @bar = (3,4);
print @foo[1,2] ~~ @bar[1,2] ? "Equal\n" : "Not equal\n";

That's probably what you need:

#!/usr/bin/perl

my @foo = (1,2);
my @bar = (3,4);
print [ @foo[1,2] ] ~~ [ @bar[1,2] ] ? "Equal\n" : "Not equal\n";
eyevan
  • 1,475
  • 8
  • 20
3

The smart match operator ~~ does its magic for arrays, not for lists. An array slice is a list, not an array.

Update:

You can solve it just by enclosing your slices into brackets, since smart match automatically dereferences:

print +([@x[0,1]] ~~ [@y[0,1]]) ? "equal\n" : "not equal\n";
choroba
  • 231,213
  • 25
  • 204
  • 289
0

Originally posted by askucins

I ran a quick query in the Perl docs related to the different behaviour of that test vs. the Perl version and I found that this was fixed in Perl 5.13.5. See "Smart matching against array slices" in perl5135delta:

Previously, the following code resulted in a successful match:

my @a = qw(a y0 z);
my @b = qw(a x0 z);
@a[0 .. $#b] ~~ @b;

This odd behaviour has now been fixed [perl #77468].

Community
  • 1
  • 1
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110