2010-08-08 79 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