This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
simplify keys(%tied_hash) in boolean context.
authorDavid Mitchell <davem@iabyn.com>
Wed, 19 Jul 2017 15:50:14 +0000 (16:50 +0100)
committerDavid Mitchell <davem@iabyn.com>
Thu, 27 Jul 2017 10:30:24 +0000 (11:30 +0100)
Previously something like

    if (keys %tied_hash) { ... }

would have called FIRSTKEY(), followed by NEXTKEY() x N.

Now, it just calls SCALAR() once if present, and if not, falls
back to calling just FIRSTKEY() once.

i.e. it only needs to determine whether at least one key is present.

The behaviour of of 'keys(%tied) in boolean context now matches that of
'(%tied) in boolean context.

See http://nntp.perl.org/group/perl.perl5.porters/245463.

pp_hot.c
t/op/tie.t

index e2d9608..a44ee34 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -993,9 +993,12 @@ S_padhv_rv2hv_common(pTHX_ HV *hv, U8 gimme, bool is_keys, bool has_targ)
          || (  PL_op->op_private & OPpMAYBE_TRUEBOOL
             && block_gimme() == G_VOID)
           )
-         && !tied
-    )
-       PUSHs(HvUSEDKEYS(hv) ? &PL_sv_yes : &PL_sv_zero);
+    ) {
+        if (tied)
+            PUSHs(Perl_hv_scalar(aTHX_ hv));
+        else
+            PUSHs(HvUSEDKEYS(hv) ? &PL_sv_yes : &PL_sv_zero);
+    }
     else if (gimme == G_SCALAR) {
         if (is_keys) {
             IV i;
index 12fc935..1f859dd 100644 (file)
@@ -1517,3 +1517,36 @@ print "$h{x}\n";
 EXPECT
 foo
 bar
+########
+# keys(%tied) in bool context without SCALAR present
+my ($f,$n) = (0,0);
+my %inner = (a =>1, b => 2, c => 3);
+sub TIEHASH  { bless \%inner, $_[0] }
+sub FIRSTKEY { $f++; my $a = scalar keys %{$_[0]}; each %{$_[0]} }
+sub NEXTKEY  { $n++; each %{$_[0]} }
+tie %h, 'main';
+my $x = !keys %h;
+print "[$x][$f][$n]\n";
+%inner = ();
+$x = !keys %h;
+print "[$x][$f][$n]\n";
+EXPECT
+[][1][0]
+[1][2][0]
+########
+# keys(%tied) in bool context with SCALAR present
+my ($f,$n, $s) = (0,0,0);
+my %inner = (a =>1, b => 2, c => 3);
+sub TIEHASH  { bless \%inner, $_[0] }
+sub FIRSTKEY { $f++; my $a = scalar keys %{$_[0]}; each %{$_[0]} }
+sub NEXTKEY  { $n++; each %{$_[0]} }
+sub SCALAR   { $s++; scalar %{$_[0]} }
+tie %h, 'main';
+my $x = !keys %h;
+print "[$x][$f][$n][$s]\n";
+%inner = ();
+$x = !keys %h;
+print "[$x][$f][$n][$s]\n";
+EXPECT
+[][0][0][1]
+[1][0][0][2]