Perl hashes don't work as expected

丶灬走出姿态 提交于 2019-12-12 19:23:18

问题


#!/usr/bin/perl

sub f { {
  a => 1,
  b => 2
} }

sub g { {
  %{f()},
  c => 3,
  d => 4,
} }

use Data::Dumper;
print Dumper g();

The above code outputs

$VAR1 = 'a';
$VAR2 = 1;
$VAR3 = 'b';
$VAR4 = 2;
$VAR5 = 'c';
$VAR6 = 3;
$VAR7 = 'd';
$VAR8 = 4;

despite in my understanding it should output

$VAR1 = {
          'a' => 1,
          'c' => 3,
          'b' => 2,
          'd' => 4
        };

What is my misunderstanding?


回答1:


The problem is that a pair of braces is ambiguous in Perl, and may be either a block or an anonymous hash

Because of the contents of the hash in your g (please use better names) perl has assumed that you are writing a code block, which is just a list of scalar values

Make it more explicit like this and your code will function as you expect

use strict;
use warnings 'all';

sub foo {
    {
        a => 1,
        b => 2,
    }
}

sub bar {
    my $href = {
        %{ foo() },
        c => 3,
        d => 4,
    }
}

use Data::Dump;
dd bar();

output

{ a => 1, b => 2, c => 3, d => 4 }



回答2:


The Perl language has ambiguities. Take for example

sub some_sub {
   {  }     # Is this a hash constructor or a block?
}

{ } is valid syntax for a block ("bare loop").
{ } is valid syntax for a hash constructor.
And both are allowed as a statement!

So Perl has to guess. Perl usually guesses correctly, but not always. In your case, it guessed correctly for f(), but not for g().

To fix this, you can give Perl "hints". Unary-+ can be used to do this. Unary-+ is a completely transparent operator; it does nothing at all. However, it must be followed by an expression (not a statement). { } has only one possible meaning as an expression.

+{ }   # Must be a hash constructor.

Similarly, you can trick Perl to guess the other way.

{; }   # Perl looks ahead, and sees that this must be a block.

So in this case, you could use

sub g { +{
  %{f()},
  c => 3,
  d => 4,
} }

or

sub g { return {
  %{f()},
  c => 3,
  d => 4,
} }

(return must also be followed by an expression if anything.)



来源:https://stackoverflow.com/questions/51613242/perl-hashes-dont-work-as-expected

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!