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

use*_*757 5 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));
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我希望"isInString"中的return语句计算为false(''或undef或者perl中可能存在的任何东西),这将作为参数#1传递给"Test",如你所知d基本上有

Test(undef, 'second parameter', 'third parameter');
Run Code Online (Sandbox Code Playgroud)

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

Test('second parameter', 'third parameter');
Run Code Online (Sandbox Code Playgroud)

从perl调试器中的isInString返回给出:

列表上下文从main :: isInString返回:空数组

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

my $bool = isInString();
Test($bool, 'second parameter', 'third parameter');
Run Code Online (Sandbox Code Playgroud)

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

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

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

        return $searchFor && $searchIn && $searchIn =~ $searchFor;
    }
Run Code Online (Sandbox Code Playgroud)

调试器仍然给出:

列表上下文从main :: isInString返回:空数组

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

cjm*_*cjm 7

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

引用perlop&&:

标量或列表上下文如果被计算,则向下传播到右操作数.

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

此外,括号强制列表上下文(由其他一些答案建议)的想法是一种常见的误解.他们没有.列表上下文是默认值; 任何可能是列表上下文的都是列表上下文.这就是没有list运营商对应的原因scalar.parens"强制"列出上下文的一个地方是重复运算符. 'a' x 3意思是'aaa',但('a') x 3意味着('a', 'a', 'a').但实际上并不是强制列表上下文中,它只是一种特殊情况下x操作.


Axe*_*man 3

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

test( !!isInString(), 'second parameter', 'third parameter' );
Run Code Online (Sandbox Code Playgroud)

通过在参数列表中调用它,您已将其强制放入“列表上下文”中。你可以用这样的东西强制它回来。一声 bang ( !) 在布尔上下文中对其求值,并将其设为 1 或''。但由于您不是测试补集,而是测试值本身,因此将另一个爆炸放在那里可以让您返回您想要的值。

但是,由于从函数体中可以清楚地看出您正在返回一个布尔值,并且您在列表上下文中调用它(参数列表列表上下文),因此您可能希望在那里强制定义一个值。就像这样:

return ($searchFor && $searchIn && $searchIn =~ $searchFor) || 0;
Run Code Online (Sandbox Code Playgroud)

Anyundef将导致错误值,并且它将跳转到 or 并返回 0,列表上下文不会像undef.