为什么我们不能在列表上下文中初始化状态数组/哈希?

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) = 42state $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到阵列上.


yst*_*sth 8

可怕的解决方法:

state @array;
state $array_is_initialized;
unless ($array_is_initialized) {
    $array_is_initialized = 1;
    @array = (1,2,3);
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为只使用闭包而不是"状态"会更容易. (3认同)
  • @AFresh1:如果空是可能的初始化值之一,则不会 (2认同)

hob*_*bbs 5

它只是没有被写入,因为它有点难,并且让它为标量工作被认为更重要.有一个opcheck(Perl_ck_sassignin op.c)可以识别赋值的左边是一个padsvop引用一个新声明的state变量并将其包装在一个特殊的onceop中,以确保赋值只发生一次 - 但它甚至都没有尝试识别列表分配,可能是由于分解(state $a, my $b, state $c) = (1, 2, 3)类型构造的困难.有趣的是,它似乎state @a = qw(blah blah blah)很容易,而且显然它比其他列表赋值变体的病态情况要小.