2010-08-08 27 views

回答

46

return;将返回列表上下文中的空列表,但在标量上下文中返回undef。即使在列表上下文中,return undef;也会始终返回单个值undef

在一般情况下,它通常不是从子程序一个好主意,return undef;通常在列表环境中使用:

sub foo { return undef } 
if (my @x = foo()) { 
    print "oops, we think we got a result"; 
} 

在一般情况下,它通常不是从子程序一个好主意,return;通常在标量上下文中使用,因为它会不会像用户希望在列表环境:

sub foo { return } 
%x = ('foo' => foo(), 'bar' => 'baz'); 
if (! exists $x{'bar'}) { 
    print "oops, bar became a value, not a key"; 
} 

这两种错误的发生相当多的实践中,后者更是这样,也许是因为预期会返回一个标潜艇更共同。如果预计会返回一个标量,那么最好返回一个标量。

+0

在第二个例子中,我会说错误不是foo的定义,而是在胖逗号的右侧有一个sub。恕我直言,这是脆弱的编程风格。 – nslntmnx 2014-08-01 00:10:18

+0

@nslntmnx:我不清楚胖逗号与它做什么或者你会做什么。你可以解释吗? – ysth 2014-08-01 00:38:04

+1

这一切都源于这样一个事实,即胖逗号不*强制标量上下文在右侧。恕我直言,在第二个例子中,亚富的定义是完美的。失败的原因是在逗号右侧有一个子呼叫的可疑编码风格。在右边有一个子呼叫(如你所示)可能导致钥匙/对被损坏,因此编码风格很脆弱。 – nslntmnx 2014-08-01 05:12:33

19

鉴于

sub foo { return; } 
sub bar { return undef; } 

在标量情况下,他们的行为相同。

my $foo = foo(); # $foo is undef 
my $bar = bar(); # $bar is undef 

在列表环境里,他们的行为不同

my @foo = foo(); # @foo is() (an empty list) 
my @bar = bar(); # @bar is (undef) (a one-element list) 

注意,一个元素的列表是在布尔上下文中的真实价值,即使唯一的元素是undef

一般来说,从子程序中通常不是一个好主意return undef;,因为它在上下文中的表现如何。

+4

这就是为什么“Perl最佳实践”(和“Perl :: Critic”)建议不要使用'return undef'。 – hillu 2010-08-08 17:49:19

+6

@hillu:这也是为什么有时使用它是个好主意的原因。例如,函数应该返回逻辑(布尔)答案,并且您希望使用另一个函数调用'foo(1,bar(),2)'。如果'bar'会用'return;'写成,你会感到惊讶;-) – 2010-08-08 18:07:52

+5

PBP出错的几件事之一。 – ysth 2010-08-08 18:37:45

2

我想我仍然同意PBP。

1)你应该避免嵌套函数调用:

my $result = bar(); 
foo(1, $result, 2); 

2)你应该始终是明确的(做 “复杂” 的事情)时:

foo(1, scalar bar(), 2); 
+0

1)它不仅仅是嵌套函数调用。 2)是的,从呼叫者的角度来看,这将是一件好事。从被调查者的角度来看,它不应该被指望。 – ysth 2010-08-11 01:37:02

+0

1)更多的例子呢? 无论如何,我相信你会最终以不稳定的结果更经常 $ perl -wle'sub get_values {return undef; };我的@values = get_values;打印标量@values;' 如果你想更加明确和正确,总有Contextual :: Return http://p3rl.org/Contextual::Return – nicomen 2010-08-11 12:23:09

+3

你的'get_values'旨在用在列表上下文中,因此应该_不''返回undef'。但是如果你有一个返回标量的'get_value'函数,它应该_always_返回一个标量,而不是一个空列表,所以它会使用'return undef'。查看ysth的答案。 – cjm 2010-09-16 21:39:30

2

书 “Perl的最佳实践”建议使用return;而不是return undef;,因为后者会在列表上下文中返回一个元素列表(其他答案已经提到了这一点)。根据这本书,这将是一个“讨厌的错误”。但是,我认为任何返回都不会导致严重的错误(可能很难找到),而在列表上下文中调用布尔函数似乎相当容易调试。

所以我总是东西(计算结果为)假我布尔函数(通常为0假,1为真)。 (是的,这也将返回列表上下文中的一个元素列表 - 因此该书中的评论在技术上是正确的 - 但是然后实际的错误将在列表上下文中调用布尔函数)。

To要清楚,我仍然推荐这本书。它提供了很多好的建议。
我在Damian Conway(O'Reilly Media,Inc.)出版的书“Perl Best Practices”中提到了第9章(子例程),第199/200页(“使用纯粹的返回来返回失败”)。 ISBN 978-0-596-00173-5。不确定是否有另一个/更新的版本。

附注:
当否定某些东西时,Perl似乎会返回一个空字符串。 my $foo = 5; return !$foo;返回q()。

+1

'!$ foo'是空字符串,因为Perl使用1表示true,空字符串表示false。由于'!',你在布尔上下文中。 – 2015-01-15 22:34:20

+0

不,'!5是规范的假值,在字符串上下文中是“”,在数字上下文中是0。 – ysth 2015-09-13 20:57:15

相关问题