2016-10-05 123 views
3

我注意到如果我用三元运算符代替if-else语句,当我尝试运行我的代码时,我最终得到编译错误。我相信罪魁祸首是我在if-else内部的foreach()循环。你知道为什么三元运算符在这个例子中的行为与if-else构造不一样吗?三元运算符不允许迭代运算符,但是if-else呢?

我的代码看起来像这样

#!/program/perl_v5.6.1/bin/perl5.6.1 

use strict; 
use warnings; 


my $fruits_array_ref = &get_fruits(); 
if($fruits_array_ref != 0) { 
    print("$_ is a fruit.\n") foreach(@$fruits_array_ref); 
} 
else { 
    print("Maybe you like vegetables?\n"); 
} 


sub get_fruits() { 
    my @fruit_list; 
    my $shopping_list = "/home/lr625/grocery_items"; 

    open(my $shopping_list_h, "<", $shopping_list) or die("Couldn't open.\n"); 
    while(my $line = <$shopping_list_h>) { 
     next if $line =~ /^\#/; 
     chomp($line); 
     push(@fruit_list, $line); 
    } 
    close($shopping_list_h) or die("Couldn't close.\n"); 

    scalar(@fruit_list) > 0 ? return(\@fruit_list) : return(0); 
} 

我的购物清单数据看起来像

# this is a header 
# to my grocery list 
apple 
banana 
grape 
orange 

我有?:运营商更换if-else现在这个样子的主要功能。

my $fruits_array_ref = &get_fruits(); 
$fruits_array_ref != 0 ? print("$_ is a fruit.\n") foreach(@$fruits_array_ref) : print("Maybe you like vegetables?\n"); 

另外,供参考我的错误说。在test.pl线8

语法错误,test.pl近 “)的foreach”

执行由于编译错误中止。

+0

它与你的问题无关,但如果你的确在使用Perl 5.6.1,你应该更新到一个新的版本,比如5.18或5.22或者你的操作系统提供的任何东西。 5.6真的很老。不过,我用5.22.1试过了你的代码,得到了同样的结果。 – PerlDuck

+0

我会,但我坚持任何工作会给我。要把我得到的东西做好。我很想解释一下,我正在试图将一个控制结构变成三元运算符中的一个操作数,所以我可能会尝试使用'do',或者我会坚持'if-else'的可预测行为 –

+1

你可能需要花时间来吸收Inferno在他的回答中所说的话。您似乎处于接近“聪明”解决方案的危险之中,而且,明智的维护“聪明”很少是一种美德。 – tjd

回答

8

if-else是一个流量控制结构,是?-:操作者认为需要表达式作为操作数。 foreach是一个流量控制结构,而不是一个表达式。

您可以通过使用do打开的任何代码块到一个表达:

$fruits_array_ref != 0 
    ? do { print "$_ is a fruit.\n" for @$fruits_array_ref } 
    : print "Maybe you like vegetables?\n"; 

但是,为什么?

1

三元运算符需要参数?:之前,请in perlop。它可以评估一个表达式并将其结果用于此。但是循环不是表达式,不能在内部运行。

对于演示 - 你可以,如果你坚持,称这将作为一个副作用打印

sub greet { say "hello" for 1..3 } 

my $x = 1; 
($x == 1) ? greet() : say "bye"; 

Actualy在生产代码中这样的功能是不同的问题,并可能是一个坏主意。整个观点将完全依赖于副作用,与我们通常想要做的相反。


解释我上面的评论 - 三元操作的要点是返回一个值,有两个值之间的选择,在一个声明。虽然它与if-else是“等价的”,但其用途(理想情况下)意味着非常不同。因此,以任何方式在?:参数内进行一些其他处理实际上是滥用符号的副作用,因为它们旨在产生要返回的值。打印出来与生成和返回值的想法相反。这不是批评,运营商经常被用作语法快捷方式。

从这个意义上说,我会建议恢复一个if-else来完成所显示的内容。

1

语句修饰符只能在语句结束时使用。

为什么使用?:?如果你想要一个结果,你通常只会这样做。

你可以在一个do {...}包裹print...foreach...,或者你可以使用map代替foreach。或者把它留作if/else。

4

其他答案已经指出,你不能按照你的方式使用三元运算符。为了完整起见,并给你一些合理的使用情况,看看下面的例子:

#1:用作子程序的参数

testSub($var eq 'test' ? 'foo' : 'bar'); 

在这里你可以看到子程序如果$var等于字符串test,则使用参数foo调用testSub。否则testSub将与bar调用。这很有用,因为您不能使用if-else结构作为子参数。

#2:用于有条件分配

my $result = $var eq 'test' ? 'foo' : 'bar'; # $result will contain 'foo' or 'bar' 

三元运算符不意味着作为一个简单的替换到if-else结构。由于它返回一个值(这里是foobar),所以也可以使用这个值使用。如果您不打算使用返回的值,则应改用通常的if-else