【问题标题】:Using my with parentheses and only one variable使用带括号且只有一个变量的 my
【发布时间】:2012-04-19 08:40:28
【问题描述】:

我有时会看到这样的 Perl 代码:

my ( $variable ) = blah....

在单个变量周围加上括号有什么意义?我认为括号仅在声明多个变量时使用,例如:

my ( $var1, $var2, $var3 ) = blah...

【问题讨论】:

  • 如果很明显列表可能是未来的预期,它可能有助于维护。我通常在读取子程序参数时使用它,例如 my ($arg1) = @_ 而不是 my $arg1 = shift
  • 我只是习惯输入m y (。而且,一个项目的列表仍然是一个列表。 :)

标签: perl


【解决方案1】:

有几种情况存在差异:

  1. 数组在右侧时

    my @array = ('a', 'b', 'c');
    my  $variable  = @array;           #  3   size of @array
    my ($variable) = @array;           # 'a'  $array[0]
    
  2. 列表在右侧时

    my  $variable  = qw/ a b c d /;    # 'd'  last  item of the list
    my ($variable) = qw/ a b c d /;    # 'a'  first item of the list
    
  3. 带有变量(数组/标量)返回值的子程序

    sub myFunction {
      ...
      return (wantarray() ? @array : $scalar);
    }
    my  $variable  = myFunction(...);  # $scalar   from the subroutine
    my ($variable) = myFunction(...);  # $array[0] from the subroutine
    

【讨论】:

    【解决方案2】:

    括号创建了一个列表上下文,它影响赋值右侧的评估方式。

    比较

    my $x = grep { /s/ } qw(apples bananas cherries);
    print $x;
    

    my ($x) = grep { /s/ } qw(apples bananas cherries);
    print $x;
    

    you just want to grab the first element of a list and discard the rest 时你会经常使用这种结构。

    【讨论】:

    • 从技术上讲,它会影响赋值运算符两边的求值方式(通过更改使用哪个赋值运算符)。
    【解决方案3】:

    我不是 Perl 专业人士(无论如何,我不是),但 AFAIK 它与列表有关。 Perl 有不同的上下文(标量、列表)。使用($var) 切换到列表上下文,$var 是标量上下文。

    my $var = (1, 2, 4); # $var = 4 (last element)
    my ($var) = (1, 2, 4); # $var = 1
    

    如果这个答案完全错误,请投反对票:)

    【讨论】:

    • 你是对的,$var = grep {; defined } (1, 2, 4); = 3 (items)
    • 还有my @a = (1,2,4); my $v = @a; print $v; = 3
    • 但是 $var = (1, 2, 4) 将 4 分配给 $vargrep 根据其上下文以特定方式运行,在标量上下文中,它提供通过测试的列表元素的数量。这与标量上下文中列表的行为不同。
    • @Borodin:是的,就像我在回答中写的那样
    【解决方案4】:

    你混淆了两个不同的东西。首先,使用my声明多个变量时,需要使用括号:

    my $foo, $bar;  
    

    不起作用,因为它被认为是两个不同的语句:

    my $foo;
    $bar;
    

    因此,您需要括号将参数组合到 函数 my:

    的参数列表中
    my($foo, $bar);
    

    其次,您有明确的分组以调用列表上下文:

    $foo, $bar = "a", "b"; # wrong!
    

    将被视为三个单独的语句:

    $foo;
    $bar = "a";
    "b";
    

    但是如果您使用括号将$foo$bar 组合成一个列表,则赋值运算符将使用列表上下文:

    ($foo, $bar) = ("a", "b");
    

    奇怪的是,如果你去掉 RHS 括号,你也会遇到一个打嗝:

    ($foo, $bar) = "a", "b"; # Useless use of a constant (b) in void context
    

    但这是因为= 运算符的优先级高于逗号,,您可以在perlop 中看到。如果你尝试:

    my @array = ("a", "b");
    ($foo, $bar) = @array;
    

    您将获得不带括号的所需行为。

    现在完成循环,让我们删除上面的列表上下文,看看会发生什么:

    my @array = ("a", "b");
    $foo = @array;
    print $foo;
    

    这将打印2,因为数组是在标量上下文中计算的,而标量上下文中的数组返回它们包含的元素数。在这种情况下,它是2

    因此,诸如此类的语句使用列表上下文:

    my ($foo) = @array;          # $foo is set to $array[0], first array element
    my ($bar) = ("a", "b", "c"); # $bar is set to "a", first list element
    

    这是一种覆盖标量分配中隐含的标量上下文的方法。为了比较,这些分配是在标量上下文中:

    my $foo = @array;            # $foo is set to the number of elements in the array
    my $bar = ("a", "b", "c");   # $bar is set to "c", last list element
    

    【讨论】:

    • 有趣的是,my $foo = ("a", "b"); print $foo; 将打印b,而不是2
    • @knittl 不像听起来那么有趣,因为只有 arrays 有这种行为,而不是列表。在标量上下文中,列表改为返回它们的最后一个元素。
    • 在标量上下文中确实没有列表这样的东西。只有标量由逗号运算符的标量版本分隔。它与$a && $b && $c 一样多。
    • @brian d foy, $x=(4,5,6); 在标量上下文中有一个列表。注意perl -MO=Concise -e'$x=(4,5,6);' 中“list”后面的“s” 列表/逗号运算符不是像&& 这样的二元运算符。
    【解决方案5】:

    我已在另一个网站上发布了关于该主题的深入 explanation

    [我不能在这里发布。 StackOverflow 不支持表格。并不是说任何人通常在异地链接到文档时都会遇到问题。]

    【讨论】:

    • 显然有人在异地链接到文档时遇到了问题。我通常建议在您的答案中添加摘要。
    • @Brad Gilbert,就我而言,将已经说过的内容重复 4 次并不是一件好事。
    • 如果您查看 StackOverflow 上的所有仅链接答案(包括已删除的答案),您会发现其中很大一部分是死链接。如果你的链接指向的地方没有像Perl Monks 那样长,我可能也会拒绝它。还有几种方法可以解决缺少表格的问题。
    • @Brad Gilbert,是的,但我确实链接到了一个与 PerlMonks 一样长的网站。
    • 我在 Stack Overflow 上指出 Link-Only answersvery much discouraged
    猜你喜欢
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多