为什么我没有从这个简短的Perl脚本中获得输出?

时间:2015-03-28 05:53:26

标签: perl return-value

为什么下面的代码没有返回任何输出?我期待它打印出“包含”。

sub is_member {
    my ($x, @list) = @_;
    foreach (@list) { 
        if ($x eq $_) {"contains"} else {"doesn't contain"}
        }
    }

my @a = qw(apple x orange but so nos how dod to it a b c);
print is_member("apple",@a)."\n";

如下面的代码运行正常,输出“is palindrome”

sub is_palindrome {
    my ($x) = @_;
    if ($x eq reverse($x)){"is palindrome"} else {"Not a palindrome"} 
    }
print is_palindrome("radar")."\n";

3 个答案:

答案 0 :(得分:6)

此代码:

if ($x eq $_) {"contains"} else {"doesn't contain"}

不会打印或返回任何内容。它评估两个常量,但这就是全部。我很惊讶没有关于丢失分号的投诉。缩进是古怪的。

你可能想要更像的东西:

sub is_member
{
    my ($x, @list) = @_;
    foreach (@list)
    { 
        return "contains" if ($x eq $_);
    }
    return "doesn't contain";
}

答案 1 :(得分:2)

for个循环没有返回值。在is_palindrome中,if语句由其自身计算,它隐式生成子例程的返回值。

对于for循环,即使在for循环中评估的最后一个语句成为返回值,最后一次比较"apple" eq "c"也将为false。

如果您想使用for循环进行测试,则需要exit the loop early。但是,在Perl中,grep是测试列表元素是否满足条件的内置方法。

my $result = (grep $_ eq $x, @list) ? "contains" : "does not contain";
print "'@list' $result $x\n";

如果您只对某个元素的存在感兴趣,List::MoreUtils::any 并且List::MoreUtils::first_index在列表很长的情况下提供了性能优势。

conditional operator$cond ? $t : $f对于编写紧凑条件非常有用,而不是尝试在带有大括号和所有大括号的单行上拟合if语句。

答案 2 :(得分:0)

澄清subs的返回值,默认情况下,Perl返回sub中最后一个表达式的求值的值...除非它在循环中。来自perldoc

  

如果没有找到返回,并且最后一个语句是表达式,则为   返回值。如果最后一个语句是循环控制结构   像foreach或while,返回值未指定。该   empty sub返回空列表。

但正如其他人所说,如果您要返回任何内容,则应始终使用return,以获得可读性和稳定性。

你的潜艇是不必要的也是如此。 grep将在标量上下文中返回0或1(可以用作布尔值),或者在数组上下文中返回新的匹配值数组;例如:

my @a = qw(apple x orange but so nos how dod to it a b c);
print "found" if grep /^orange$/, @a; # prints "found"
my @b = grep length > 3, @a; 
print "@b" # prints "apple orange"