From: Rafael Garcia-Suarez Date: Wed, 4 Mar 2009 20:14:10 +0000 (+0100) Subject: The new smart match dispatch table for 5.10.1 onwards X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=202d7cbdf6efc5f9c138c4460dce6d5b72603d2b;p=p5sagit%2Fp5-mst-13.2.git The new smart match dispatch table for 5.10.1 onwards This /does/ break backwards compatibility. Changes to come are: - ~~ is no longer commutative. Dispatch is now done based on the (run-time) type of the right side argument. - The right side can be a ".." range, which will be treated specially, and no longer as a boolean operator (as in scalar context). - when() should treat "..." as a boolean operator. - Coderefs with an empty prototype are no longer special. - Any ~~ Array distributes the smart match test. - Comparing two coderefs is no longer a special case and does not perform referential equality. (Use \&foo ~~ "".\&bar for that.) This patch also documents that ~~ won't work on objects that don't overload it, except in the expression $object ~~ undef. --- diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index 56b65d5..2e1f4c5 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -588,6 +588,11 @@ exclusive-or C<(...) xor (...)>. a filetest operator, with the exception of C<-s>, C<-M>, C<-A>, and C<-C>, that return numerical values, not boolean ones. +=item * + +the C<...> flip-flop operator (but B the two-dot version C<..>, which +is used to construct and test against numerical or string ranges). + =back In those cases the value of EXPR is used directly as a boolean. @@ -665,47 +670,55 @@ variable C<$_>. (You can use C.) =head3 Smart matching in detail -The behaviour of a smart match depends on what type of thing -its arguments are. It is always commutative, i.e. C<$a ~~ $b> -behaves the same as C<$b ~~ $a>. The behaviour is determined -by the following table: the first row that applies, in either -order, determines the match behaviour. - +The behaviour of a smart match depends on what type of thing its arguments +are. The behaviour is determined by the following table: the first row +that applies determines the match behaviour (which is thus mostly +determined by the type of the right operand). Note that the smart match +implicitly dereferences any hash or array ref, so the "Hash" and "Array" +entries apply in those cases. $a $b Type of Match Implied Matching Code ====== ===== ===================== ============= - (overloading trumps everything) + Any undef undefined !defined $a + + (overloading trumps everything below) - Code[+] Code[+] referential equality $a == $b - Any Code[+] scalar sub truth $b->($a) + Hash CodeRef sub truth for each key !grep { !$b->($_) } keys %$a + Array CodeRef sub truth for each elt !grep { !$b->($_) } @$a + Any CodeRef scalar sub truth $b->($a) Hash Hash hash keys identical [sort keys %$a]~~[sort keys %$b] + Array Hash hash slice existence @$a == grep {exists $b->{$_}} @$a + Regex Hash hash key grep grep /$a/, keys %$b + undef Hash always false (undef can't be a key) + Any Hash hash entry existence exists $b->{$a} + Hash Array hash slice existence @$b == grep {exists $a->{$_}} @$b - Hash Regex hash key grep grep /$b/, keys %$a - Hash Any hash entry existence exists $a->{$b} + Array Array arrays are comparable[1] + Any Array match against an array element[2] + grep $a ~~ $_, @$b - Array Array arrays are identical[*] + Hash Regex hash key grep grep /$b/, keys %$a Array Regex array grep grep /$b/, @$a - Array Num array contains number grep $_ == $b, @$a - Array Any array contains string grep $_ eq $b, @$a - - Any undef undefined !defined $a Any Regex pattern match $a =~ /$b/ - Code() Code() results are equal $a->() eq $b->() - Any Code() simple closure truth $b->() # ignoring $a - Num numish[!] numeric equality $a == $b + + Num Range[3] in numeric range + undef Range[3] always false + Any Range[3] in string range + + Num numish[4] numeric equality $a == $b Any Str string equality $a eq $b Any Num numeric equality $a == $b - Any Any string equality $a eq $b - + - this must be a code reference whose prototype (if present) is not "" - (subs with a "" prototype are dealt with by the 'Code()' entry lower down) - * - that is, each element matches the element of same index in the other - array. If a circular reference is found, we fall back to referential - equality. - ! - either a real number, or a string that looks like a number + 1 - that is, each element matches the element of same index in the other + array. [2] + 2 - If a circular reference is found, we fall back to referential equality. + 3 - a range is written EXPR..EXPR (using the C<..> range operator, but + NOT the three-dot version C<...>, which will be treated as a boolean + operator) + 4 - either a real number, or a string that looks like a number The "matching code" doesn't represent the I matching code, of course: it's just there to explain the intended meaning. Unlike @@ -717,6 +730,11 @@ You can change the way that an object is matched by overloading the C<~~> operator. This trumps the usual smart match semantics. See L. +It should be noted that C<~~> will refuse to work on objects that +don't overload it (in order to avoid relying on the object's +underlying structure). The only exception is when testing for +definedness with C<$object ~~ undef>. + =head3 Differences from Perl 6 The Perl 5 smart match and C/C constructs are not