Perl使用子调用作为另一个子意外上下文的参数

时间:2010-07-30 20:57:42

标签: perl compiler-errors

我使用子调用作为另一个子的参数。示例代码:

test(isInString(), 'second parameter', 'third parameter');

sub test {
    my ($boolean, $second, $third) = @_;
    print "boolean: $boolean\n second: $second\n third: $third\n";
}

sub isInString {
    my $searchFor = 'a'; 
    my $searchIn = 'bcd';   

    return ($searchFor && $searchIn && ($searchIn =~ $searchFor));
}

在上面的例子中,我希望“isInString”中的return语句计算为false(''或undef或perl中的任何内容),这将作为参数#1传递给“Test”,你基本上已经

Test(undef, 'second parameter', 'third parameter');

但事实并非如此。 isInString返回一个空数组,基本上你得到的是

Test('second parameter', 'third parameter');

从perl调试器中的isInString返回:

从main :: isInString返回

列表上下文:   空数组

我假设这是一个perl上下文的东西,我可以先分配一个标量变量,它可以正常工作:

my $bool = isInString();
Test($bool, 'second parameter', 'third parameter');

调试器给出 - 标量上下文从main :: isInString返回:''

编辑我删除了所有具有相同结果的parens:

sub isInString {
        my $searchFor = 'a'; 
        my $searchIn = 'bcd';   

        return $searchFor && $searchIn && $searchIn =~ $searchFor;
    }

调试器仍然给出:

从main :: isInString返回

列表上下文:   空数组

有人可以解释为什么它会在这种情况下返回列表上下文/空数组吗?

3 个答案:

答案 0 :(得分:7)

您的return在列表上下文中进行评估,因为该函数是在列表上下文中调用的。布尔运算符(如&&)执行而不是强制标量上下文。

引用perlop on &&

  

标量或列表上下文向下传播   如果是的话,到右边的操作数   评价。

由于匹配运算符在列表上下文中失败时返回一个空列表,这就是你得到的。如果要强制使用标量上下文,请在scalar语句中或在调用函数时使用return运算符。

此外,括号强制列表上下文(由其他一些答案建议)的想法是一种常见的误解。他们没有。列表上下文是默认值; 可以列出上下文的任何内容都是列表上下文。这就是为什么没有list运算符与scalar对应的原因。 parens“强制”列出上下文的一个地方是重复运算符。 'a' x 3表示'aaa',但('a') x 3表示('a', 'a', 'a')。但这实际上不是强制列表上下文,它只是the x operator的一个特例。

答案 1 :(得分:3)

如果要强制使用“布尔上下文”,可以使用双阴影“运算符”:!!,如下所示:

test( !!isInString(), 'second parameter', 'third parameter' );

通过在参数列表中调用它,您已将其强制转换为“列表上下文”。你可以用这样的东西强制它。一次爆炸(!)在布尔上下文中对其进行评估,并使其为1或''。但既然你没有测试补充,而是价值本身,把另一个爆炸放在那里可以让你回到你想要的价值。

但是,因为从函数体中可以清楚地看到你返回一个布尔值,并且你在列表上下文中调用它(参数的列表是列表上下文),可能想在那里强制定义的值。像这样:

return ($searchFor && $searchIn && $searchIn =~ $searchFor) || 0;

任何undef都会导致false值,它会跳转到或返回0,列表上下文不会忽略undef

答案 2 :(得分:0)

与您的问题无关,但index()

isInString()