From: Rafael Garcia-Suarez Date: Tue, 17 Mar 2009 14:34:24 +0000 (+0100) Subject: Document that empty sets don't smart-match X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=168ff818262576c8ec771f99cf50b7095a83e10c;p=p5sagit%2Fp5-mst-13.2.git Document that empty sets don't smart-match (and implement this for the C<~~ coderef> form) --- diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index 2e1f4c5..52a3f87 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -683,42 +683,43 @@ entries apply in those cases. (overloading trumps everything below) - 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 CodeRef sub truth for each key[1] !grep { !$b->($_) } keys %$a + Array CodeRef sub truth for each elt[1] !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 + Regex Hash hash key grep[1] 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 - Array Array arrays are comparable[1] - Any Array match against an array element[2] + Hash Array hash slice existence[1] @$b == grep {exists $a->{$_}} @$b + Array Array arrays are comparable[2] + Any Array match against an array element[3] grep $a ~~ $_, @$b Hash Regex hash key grep grep /$b/, keys %$a Array Regex array grep grep /$b/, @$a Any Regex pattern match $a =~ /$b/ - Num Range[3] in numeric range - undef Range[3] always false - Any Range[3] in string range + Num Range[4] in numeric range + undef Range[4] always false + Any Range[4] in string range - Num numish[4] numeric equality $a == $b + Num numish[5] numeric equality $a == $b Any Str string equality $a eq $b Any Num numeric equality $a == $b Any Any string equality $a eq $b - 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 + 1 - empty hashes or array won't match. + 2 - that is, each element matches the element of same index in the other + array. [3] + 3 - If a circular reference is found, we fall back to referential equality. + 4 - 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 + 5 - 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 diff --git a/pp_ctl.c b/pp_ctl.c index 0b172c5..1b4bbf5 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -4091,7 +4091,9 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) HE *he; bool andedresults = TRUE; HV *hv = (HV*) SvRV(d); - (void) hv_iterinit(hv); + I32 numkeys = hv_iterinit(hv); + if (numkeys == 0) + RETPUSHNO; while ( (he = hv_iternext(hv)) ) { ENTER; SAVETMPS; @@ -4118,6 +4120,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) bool andedresults = TRUE; AV *av = (AV*) SvRV(d); const I32 len = av_len(av); + if (len == -1) + RETPUSHNO; for (i = 0; i <= len; ++i) { SV * const * const svp = av_fetch(av, i, FALSE); ENTER; diff --git a/t/op/smartmatch.t b/t/op/smartmatch.t index c480e0e..5fd3587 100644 --- a/t/op/smartmatch.t +++ b/t/op/smartmatch.t @@ -212,8 +212,8 @@ __DATA__ ! [1] \&foo ! {a=>1} \&foo # empty stuff matches, because the sub is never called: - [] \&foo - {} \&foo +! [] \&foo +! {} \&foo ! qr// \&foo ! undef \&foo undef \&bar @@ -224,8 +224,8 @@ __DATA__ @ "foo" \&fatal @ qr// \&fatal # sub is not called on empty hashes / arrays - [] \&fatal - +{} \&fatal +! [] \&fatal +! +{} \&fatal # - null-prototyped subs ! undef \&FALSE