From cba5a3b05660d6a40525beb667a389a690900298 Mon Sep 17 00:00:00 2001 From: David Golden Date: Thu, 9 Sep 2010 17:22:02 -0400 Subject: Allow push/pop/keys/etc to act on references All built-in functions that operate directly on array or hash containers now also accept hard references to arrays or hashes: |----------------------------+---------------------------| | Traditional syntax | Terse syntax | |----------------------------+---------------------------| | push @$arrayref, @stuff | push $arrayref, @stuff | | unshift @$arrayref, @stuff | unshift $arrayref, @stuff | | pop @$arrayref | pop $arrayref | | shift @$arrayref | shift $arrayref | | splice @$arrayref, 0, 2 | splice $arrayref, 0, 2 | | keys %$hashref | keys $hashref | | keys @$arrayref | keys $arrayref | | values %$hashref | values $hashref | | values @$arrayref | values $arrayref | | ($k,$v) = each %$hashref | ($k,$v) = each $hashref | | ($k,$v) = each @$arrayref | ($k,$v) = each $arrayref | |----------------------------+---------------------------| This allows these built-in functions to act on long dereferencing chains or on the return value of subroutines without needing to wrap them in C<@{}> or C<%{}>: push @{$obj->tags}, $new_tag; # old way push $obj->tags, $new_tag; # new way for ( keys %{$hoh->{genres}{artists}} ) {...} # old way for ( keys $hoh->{genres}{artists} ) {...} # new way For C, C and C, the reference will auto-vivify if it is not defined, just as if it were wrapped with C<@{}>. Calling C or C directly on a reference gives a substantial performance improvement over explicit dereferencing. For C, C, C, when overloaded dereferencing is present, the overloaded dereference is used instead of dereferencing the underlying reftype. Warnings are issued about assumptions made in the following three ambiguous cases: (a) If both %{} and @{} overloading exists, %{} is used (b) If %{} overloading exists on a blessed arrayref, %{} is used (c) If @{} overloading exists on a blessed hashref, @{} is used --- doop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'doop.c') diff --git a/doop.c b/doop.c index 35efba69b3..550e6fb2b6 100644 --- a/doop.c +++ b/doop.c @@ -1436,8 +1436,9 @@ Perl_do_kv(pTHX) register HE *entry; const I32 gimme = GIMME_V; const I32 dokv = (PL_op->op_type == OP_RV2HV || PL_op->op_type == OP_PADHV); - const I32 dokeys = dokv || (PL_op->op_type == OP_KEYS); - const I32 dovalues = dokv || (PL_op->op_type == OP_VALUES); + /* op_type is OP_RKEYS/OP_RVALUES if pp_rkeys delegated to here */ + const I32 dokeys = dokv || (PL_op->op_type == OP_KEYS || PL_op->op_type == OP_RKEYS); + const I32 dovalues = dokv || (PL_op->op_type == OP_VALUES || PL_op->op_type == OP_RVALUES); if (!hv) { if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */ -- cgit v1.2.1