Perl:定义哈希引用相同的哈希,$ this - > {key}?

SJa*_*r13 5 perl

我将如何创建如下的哈希:

my %hash = (key1=>"Something", key2=>$hash{key1} . "Else");
Run Code Online (Sandbox Code Playgroud)

当我声明哈希时,这不能做到吗?到目前为止,我唯一想到的是:

my %hash = (key1=>"Something");
$hash{key2} = $hash{key1} . "Else";
Run Code Online (Sandbox Code Playgroud)

dao*_*oad 11

为什么不使用中间变量?

my $common_value = 'Something';
my %some_hash = ( k1 => $common_value, k2 => $common_value.'Else' );
Run Code Online (Sandbox Code Playgroud)

更新

kemp问我们为什么需要一个中间变量.我可以用两种方式解释这个问题,我会尽力回答这两种解释.

  1. 你为什么不能这样做my %hash = ( k1 => 'foo', k2 => $hash{k1}.'bar' );

    表达式的右侧(rhs)在左侧(lhs)之前进行评估.因此,当k2确定值时,%hash尚未发生任何分配.事实上,%hash甚至还没有创建并进入暂存区.(%hash这里是一个词法变量,所以它不会进入符号表.)

  2. 为什么使用变量而不是其他方法?

    好吧,有很多方法可以用这样的值初始化哈希.如果我有少量相关的键进行初始化,我会使用一个中间变量.

    my $cv1 = sub_result() * 5;
    my $cv2 = "Number: $cv1";
    
    my %h = (
        k1 => $cv1,  
        k2 => $cv2,
        k3 => "Numero: $cv1",
        k4 => "Big $cv2",
        k5 => "Round $cv2",
        k6 => "Whole $cv2",
        k7 => "-$cv1",
    );
    
    Run Code Online (Sandbox Code Playgroud)

    但是,如果我必须构建许多依赖于许多不同键的复杂值,我可能会使用数据驱动方法来初始化哈希.确切的实现将取决于我没有的细节,但它可能看起来像这样:

    use Scalar::Util qw(reftype);
    
    my @init = ( 
        [ key1 => $value                 ],
        [ key2 => \&make_a_value, 'key1' ],
        [ key3 => \&another_way,  'key2' ],
    );
    
    my %h; 
    for my $spec ( @init ) {
        my $key   = shift @$spec;
        my $value = shift @$spec;
        my @args  = @$spec;
    
        if( reftype $value eq reftype sub {} ) {
            $value = $value->( @h{ @args } );
        }
    
        $h{$key} = $value;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    对于这个问题所针对的任何情况,选择使用什么技术取决于许多对该实例特殊的细节.因此,我们必须做出通用陈述.中间变量是解决OP问题的一种好方法.他们是否应该在他的特定情况下使用,我不能说.


DVK*_*DVK 9

它有两个原因无法完成:

  1. 在Perl处理时key2 => $hash{key1},它尚未将分配有密钥1的内存与散列名称散列相关联.换句话说,$hash{key1}直到key2 => $hash{key1}已经分配之后才指向内存中的正确位置.

  2. 之前的原因没有说明额外的问题:您在%hash处理时key2 => $hash{key1}(还是解析/评估的顺序)还没有放入符号表,因此如果use strict;您一如既往,编译器将会进行barf .my %hash在先前的陈述中声明这个很容易解决,但#1不是.