Cha*_*hak 13 perl initialization
数组和散列有一个限制作为状态变量.从Perl 5.10开始,我们无法在列表上下文中初始化它们:
所以
state @array = qw(a b c); #Error!
Run Code Online (Sandbox Code Playgroud)
为什么会这样?为什么不允许这样做?
我们可以使用状态数组并通过这种方式初始化它们
state @numbers;
push @numbers, 5;
push @numbers, 6;
Run Code Online (Sandbox Code Playgroud)
但为什么不直接这样做呢 state @numbers = qw(5 6);
Perl为什么不允许它?
cjm*_*cjm 15
根据perldiag,计划在将来的版本中支持列表上下文初始化:
- 当前禁止列表上下文中状态变量的初始化
(F)目前,"状态"的实现仅允许在标量上下文中初始化标量变量.重新写state ($a) = 42为state $a = 42从列表改变为标量上下文.state (@a) = foo()未来的perl版本将支持诸如此类的构造.
目前,禁止所有列表赋值初始化状态变量,因为Perl 6中的精确语义不明确.最好使它成为语法错误,而不是现在有一个行为,但稍后更改它.[我相信这是共识.如果没有,它将被退出]
您总是可以使用arrayref:
state $arrayRef = [qw(a b c)];
Run Code Online (Sandbox Code Playgroud)
请注意你的例子
state @numbers;
push @numbers, 5;
push @numbers, 6;
Run Code Online (Sandbox Code Playgroud)
不不意味着同样的事情state @numbers = qw(5 6)会(如果它的工作).甲state变量只初始化一次,但是您的代码将每一个被执行的代码的时间推5&6到阵列上.
可怕的解决方法:
state @array;
state $array_is_initialized;
unless ($array_is_initialized) {
$array_is_initialized = 1;
@array = (1,2,3);
}
Run Code Online (Sandbox Code Playgroud)
它只是没有被写入,因为它有点难,并且让它为标量工作被认为更重要.有一个opcheck(Perl_ck_sassignin op.c)可以识别赋值的左边是一个padsvop引用一个新声明的state变量并将其包装在一个特殊的onceop中,以确保赋值只发生一次 - 但它甚至都没有尝试识别列表分配,可能是由于分解(state $a, my $b, state $c) = (1, 2, 3)类型构造的困难.有趣的是,它似乎state @a = qw(blah blah blah)很容易,而且显然它比其他列表赋值变体的病态情况要小.