我将如何创建如下的哈希:
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问我们为什么需要一个中间变量.我可以用两种方式解释这个问题,我会尽力回答这两种解释.
你为什么不能这样做my %hash = ( k1 => 'foo', k2 => $hash{k1}.'bar' );?
表达式的右侧(rhs)在左侧(lhs)之前进行评估.因此,当k2确定值时,%hash尚未发生任何分配.事实上,%hash甚至还没有创建并进入暂存区.(%hash这里是一个词法变量,所以它不会进入符号表.)
为什么使用变量而不是其他方法?
好吧,有很多方法可以用这样的值初始化哈希.如果我有少量相关的键进行初始化,我会使用一个中间变量.
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问题的一种好方法.他们是否应该在他的特定情况下使用,我不能说.
它有两个原因无法完成:
在Perl处理时key2 => $hash{key1},它尚未将分配有密钥1的内存与散列名称散列相关联.换句话说,$hash{key1}直到key2 => $hash{key1}已经分配之后才指向内存中的正确位置.
之前的原因没有说明额外的问题:您在%hash处理时key2 => $hash{key1}(还是解析/评估的顺序)还没有放入符号表,因此如果use strict;您一如既往,编译器将会进行barf .my %hash在先前的陈述中声明这个很容易解决,但#1不是.