【问题标题】:Backslash before a subroutine call子程序调用前的反斜杠
【发布时间】:2015-06-04 10:50:29
【问题描述】:

当我理解引用中 [] 和 \ 之间的区别时,我在子例程中都使用了前者很好,但是当我稍后尝试时,我认为它应该给出错误,但是 perl 中的以下程序

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my @b;
for my $i ( 0 .. 10 ) {
    $b[$i] = \somefunc($i);

}
print Dumper( \@b );

sub somefunc {
    my $n = shift;
    my ( @a, $k );
    for my $j ( 11 .. 13 ) {
        $k = $n * $j;
        push( @a, $k );
    }
    print "a: @a \n";
    return @a;
}

输出为:

a: 0 0 0 
a: 11 12 13 
a: 22 24 26 
a: 33 36 39 
a: 44 48 52 
a: 55 60 65 
a: 66 72 78 
a: 77 84 91 
a: 88 96 104 
a: 99 108 117 
a: 110 120 130 
$VAR1 = [
      \0,
      \13,
      \26,
      \39,
      \52,
      \65,
      \78,
      \91,
      \104,
      \117,
      \130
    ];

我无法理解输出。需要解释。

【问题讨论】:

  • 你打算在你的列表中加入什么?

标签: perl reference subroutine


【解决方案1】:

这里发生的事情是:

您正在从somefunc 返回一个数组。

但是你将它分配给一个标量。因此,实际上所做的只是将数组中的最后一个值放入标量值中。

my $value =  ( 110, 120, 130 );
print $value;

当你这样做时 - $value 被设置为数组中的最后一个值。这就是您的代码中实际发生的情况。例如见perldata:

列表值通过用逗号分隔各个值来表示(并在需要优先级的地方将列表括在括号中): (LIST)

在不需要列表值的上下文中,看起来是列表文字的值只是最后一个元素的值,就像 C 逗号运算符一样。例如,

@foo = ('cc', '-E', $bar);

将整个列表值分配给数组@foo,但是

foo = ('cc', '-E', $bar);

将变量$bar 的值赋给标量变量$foo。请注意,标量上下文中实际数组的值是数组的长度;下面将值 3 分配给 $foo:

@foo = ('cc', '-E', $bar); $foo = @foo; # $foo gets 3

后一种情况通常是问题所在,因为它是标量上下文中的列表。

在您的示例中 - 反斜杠前缀表示“引用” - 这在很大程度上没有意义,因为它是对数字的引用。

但对于标量,它可能更有意义:

my $newvalue = "fish"; 
my $value =  ( 110, 120, 130, \$newvalue );
print Dumper $value;

$newvalue = 'barg'; 
print Dumper $value;

给予:

$VAR1 = \'fish';
$VAR1 = \'barg';

这就是您获得结果的原因。带有斜线的前缀表示您正在获取对结果的引用,而不是对子的引用。对130 的引用实际上并不那么有意义。

通常,在执行上述分配时 - 您会收到关于 Useless use of a constant (110) in void context 的警告,但当您有子例程返回时,这并不适用。

如果您想插入 sub 引用,则需要添加 &,但如果您只想通过引用插入返回的数组 - 您需要:

$b[$i] = [somefunc($i)]

或者:

return \@a;

【讨论】:

  • 好吧,但是为什么标量上下文中的列表会计算为列表的最后一个元素?
  • 忍受我。我会尝试挖掘它的引用。
  • 顺便说一句,您的程序正在输出:$VAR1 = \'fish'; $VAR1 = \\'barg';
  • 是的,疏忽 - print Dumper \$valueprint Dumper $value; 之间的区别。你真的需要哈希/数组的反斜杠。
  • 学究式地,子例程永远不能返回数组。子程序总是返回一个列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2019-01-13
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多