【问题标题】:Why can't we initialize state arrays/hashes in list context?为什么我们不能在列表上下文中初始化状态数组/哈希?
【发布时间】:2011-10-05 20:53:24
【问题描述】:

数组和散列作为状态变量是有限制的。从 Perl 5.10 开始,我们无法在列表上下文中初始化它们:

所以

state @array = qw(a b c); #Error!

为什么会这样?为什么不允许这样做?

我们可以使用状态数组并通过这种方式进行初始化

state @numbers;
push @numbers, 5;
push @numbers, 6;

但是为什么不直接通过state @numbers = qw(5 6);来做呢

为什么 Perl 不允许这样做?

【问题讨论】:

    标签: perl initialization


    【解决方案1】:

    我认为您的问题没有很好的答案。我不能肯定地说,但我的猜测是 perl 从来不支持你的第一个代码所暗示的一次性初始化(我假设这就是你想要的)。

    你可以这样做:

    state @array;
    @array = qw( a b c );
    

    这样做与使用“我的”变量而不是“状态”变量是一样的。

    【讨论】:

    • 我询问了状态数组/哈希不是我的:-/
    • @Ron 有不同的效果。 state $x = 42 仅将 $x 设置为 42 一次state $x; $x = 42 每次运行时都将 $x 设置为 42。 state @array = qw(a b c) 根本不起作用,但state @array; @array = qw(a b c) 每次运行时都会重置@array 的值。
    【解决方案2】:

    根据perldiag,计划在未来的版本中支持列表上下文初始化:

    • 当前禁止在列表上下文中初始化状态变量
      (F) 目前“状态”的实现只允许在标量上下文中初始化标量变量。将state ($a) = 42 重写为state $a = 42 以从列表更改为标量上下文。未来的 perl 版本将支持 state (@a) = foo() 等结构。

    根据this message about the change that made this an error

    现在,禁止所有状态变量的列表赋值初始化, 因为 Perl 6 中的精确语义尚不清楚。最好让它成为 语法错误,而不是现在有一种行为,但以后再改变。 【我相信这是共识。如果没有,则退出]

    你总是可以使用 arrayref 来代替:

    state $arrayRef = [qw(a b c)];
    

    注意你的例子

    state @numbers;
    push @numbers, 5;
    push @numbers, 6;
    

    state @numbers = qw(5 6) 的含义相同(如果有效)。 state 变量只初始化一次,但每次执行该代码时,您的代码都会将 5 和 6 推送到数组中。

    【讨论】:

      【解决方案3】:

      可怕的解决方法:

      state @array;
      state $array_is_initialized;
      unless ($array_is_initialized) {
          $array_is_initialized = 1;
          @array = (1,2,3);
      }
      

      【讨论】:

      • 我认为只使用闭包而不是 state 会更容易。
      • 另外,如果@array 未初始化,@array 的计算结果为 false,所以这可能是:state @array; if (!@array) { @array = 1, 2, 3; }
      • @AFresh1: 如果空是可能的初始化值之一,则不是
      【解决方案4】:

      它根本没有被写出来,因为它有点难,而且让它为标量工作被认为更重要。有一个 opcheck(op.c 中的Perl_ck_sassign)可以识别赋值左侧何时是 padsv 操作,该操作引用新声明的 state 变量并将其包装在特殊的 once 操作中,以确保分配只发生一次——但它甚至不尝试识别列表分配,可能是由于难以分解 (state $a, my $b, state $c) = (1, 2, 3) 类型构造。不过有趣的是,state @a = qw(blah blah blah) 似乎很容易,而且显然它比其他列表分配变体更不病态。

      【讨论】:

        【解决方案5】:

        另一种解决方法:

        {
            my @array = qw(1 2 3);
            sub foo {
                print join(", ", @array);
            }
        }
        
        foo();
        

        提供与使用状态类似的结果(在这种情况下,将其范围限定为函数,而在离开函数时不会破坏它)。使用函数声明在 Perl 中是全局的这一事实。

        Source

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-09
          • 2012-01-07
          • 2015-01-20
          • 1970-01-01
          • 2012-05-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多