Perl中的嵌套函数调用

Perl中的嵌套函数调用,perl,Perl,我不得不为我的工作编辑一些Perl脚本。我从来没有写过一行Perl,但我可以让我的东西正常工作,直到我遇到一个奇怪的问题。考虑以下函数 sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s } 通过以下两种方式进行调用: my $previousVersionHash = readline( *CONFIG ); $previousVersionHash = trim($previousVersionH

我不得不为我的工作编辑一些Perl脚本。我从来没有写过一行Perl,但我可以让我的东西正常工作,直到我遇到一个奇怪的问题。考虑以下函数

sub trim {
    my $s = shift; 
    $s =~ s/^\s+|\s+$//g; 
    return $s 
}
通过以下两种方式进行调用:

my $previousVersionHash = readline( *CONFIG );
$previousVersionHash = trim($previousVersionHash);
$maxClients = readline( *CONFIG );

在第一种情况下,它工作正常,但在第二个代码段中,我得到警告,$maxClients为空,而不是包含配置文件的第二行


为什么会有这种奇怪的行为?请注意,当我使用sub trim$时也会发生这种情况。顺便说一句,我不知道这两个声明之间的区别,但这是有文档记录的,这样我就可以看看这对这个问题是否重要。

Perl将允许它现在调用的函数返回列表或标量。你跟我核对一下。当您在列表上下文中调用它时,readline会将所有行读取到数组中,就像您在第二个示例中所做的那样

第二种方法是这样调用它,因为like@thisuiteisblacknot的注释说,用户定义的子例程的参数总是在列表上下文中进行计算,假设没有原型:

my @array = readline( *CONFIG );
trim(@array);
因此,这里所有剩余的*CONFIG行都放在了数组@array中。修剪函数将丢弃除第一个值以外的所有其他值

要解决此问题并强制在标量上下文中调用trim,请执行以下操作:

my $previousVersionHash = trim(scalar(readline( *CONFIG )));
或者继续像你那样称呼它

要更新trim以支持阵列,您可以尝试以下操作:

sub trim {
    my @a;
    foreach my $s (@_) {
        $s =~ s/^\s+|\s+$//g; 
        push @a, $s;
    }
    return @a;
}

好的,这很酷,所以如果我想的话,我可以将trim函数应用于所有的行,然后简单地从数组中读取。这将使我的代码剩下的部分变得更好:干杯!上下文在Perl中是一个令人困惑但功能强大的特性,而不是在任何其他语言中都可能遇到的特性?我将检查/array context/list context/。另外,我认为您在这里遗漏了关键点:用户定义子例程的参数总是在列表上下文中进行计算,假设没有原型。@ThisSuitesBlackNot:谢谢。更新了我的答案。我确实告诉过你,sub是在列表上下文中评估的,即使我没有详细说明。如果你说sub trim$,问题就不会发生。这就是说,学习处理为参数提供列表上下文的子调用比处理原型要好,所以trimscalar readline。。。如果测试这个对我来说不是那么痛苦,我会尝试添加回参数列表
sub trim {
    my @a;
    foreach my $s (@_) {
        $s =~ s/^\s+|\s+$//g; 
        push @a, $s;
    }
    return @a;
}