in reply to Incorrect warning when using hash slices?

Definitely a bug.

$ perl -c -we'my %f; my @a = @f{qw# a b #}' Scalar value @f{qw# a b #} better written as $f{qw# a b #} at -e line +1. -e syntax OK

Still warns at least as recently as v5.13.10.

It seems to only warn for some delimiters.

$ perl -c -we'my %f; my @a = @f{qw( a b )}' -e syntax OK $ perl -c -we'my %f; my @a = @f{qw! a b !}' -e syntax OK $ perl -c -we'my %f; my @a = @f{qw# a b #}' Scalar value @f{qw# a b #} better written as $f{qw# a b #} at -e line +1. -e syntax OK $ perl -c -we'my %f; my @a = @f{qw$ a b $}' Scalar value @f{qw$ a b $} better written as $f{qw$ a b $} at -e line +1. -e syntax OK

Created ticket RT#89294

Replies are listed 'Best First'.
Re^2: Incorrect warning when using hash slices?
by davido (Cardinal) on Apr 26, 2011 at 16:50 UTC

    I'm wondering if this relates to perl having difficulty distinguishing between the qw## operator versus a bare hash key that looks like qw##. I guess there's not much to wonder about there. That seems to be what's happening:

    use 5.010_001; use strict; use warnings; my %hash = qw/ one um two dois /; { local $, = "\t"; say @hash{ qw# one two # }; say @hash{ (qw# one two #) }; }

    Output is:

    Scalar value @hash{ qw# one two # } better written as $hash{ qw# one t +wo # } at mytest.pl line 12. um dois um dois

    Only one warning. The second hash slice uses parens to disambiguate the intent of whether qw## represents a hash key, or a qw## operator.

    By the way, if I use diagnostics, I get:

    Scalar value @hash{ qw# one two # } better written as $hash{ qw# one two # } at mytest.pl line 13 (#1) (W syntax) You've used a hash slice (indicated by @) to select a single element of a hash. Generally it's better to ask for a scalar value (indicated by $). The difference is that $foo{&bar} always behaves like a scalar, both when assigning to it and when evaluating its argument, while @foo{&bar} behaves like a list when you assign to it, and provides a list context to its subscript, which can do weird things if you're expecting only one subscript. On the other hand, if you were actually hoping to treat the hash element as a list, you need to look into how references work, because Perl will not magically convert between scalars and lists for you. See perlref.

    ...which seems to support that qr## is being seen by the warnings pragma as a hash key instead of a list constructor. On the other hand, perl still sees it as a list constructor, and does the right thing. I know just about zero with regards to Perl's internal code, but it would seem the culprit is within the warnings mechanism.

    But I'm putting this out there for discussion's sake. I'm as curious as anyone and am just speculating reasons.


    Dave

      I'm wondering if this relates to perl having difficulty distinguishing between the qw## operator versus a bare hash key that looks like qw##.

      B::Deparse to the rescue:

      $ perl -MO=Deparse -wE '$foo{a}=1; $foo{b}=2; say join",", @foo{qw#a b +#}' BEGIN { $^W = 1; } BEGIN { $^H{'feature_unicode'} = q(1); $^H{'feature_say'} = q(1); $^H{'feature_state'} = q(1); $^H{'feature_switch'} = q(1); } $foo{'a'} = 1; $foo{'b'} = 2; say join(',', @foo{'a', 'b'}); -e syntax OK

      So it deparses correctly to @foo{'a', 'b'}

      When I used / instead of # as a delimiter, I get the same deparse, and no warning on running. So I don't see parsing issues as the reason for this bug.