2015-04-20 65 views
1

我必須做的功能,將作爲標量和數組工作。例如:標量或數組函數

@t = testfunc(1, 2, 3, 4); 
$x = testfunc(1, 2, 3, 4); 

有人知道我該怎麼做嗎? 它必須打印「標量」如果它是$ x並打印「數組」如果@t。我試圖做這樣的事情:

sub testfunc() 
{ 
    print "test"; 
} 

但是,即使這不工作:/

+2

正如其他人已經指出,你會使用'wantarray'這個。請參閱'perldoc -f wantarray' http://perldoc.perl.org/functions/wantarray.html – shawnhcorey

+6

不要使用原型(子名稱後的空括號)。它們的用法是* only *來覆蓋正常的子例程功能,以創建模仿某些內置插件行爲的模糊事物。 – TLP

+1

@TLP:除非你有5.20+並且已經啓用了實驗簽名(但是即使在這種情況下,'()'也不適合) – ysth

回答

4

此功能被命名爲「呼叫內容」。使用wantarray關鍵字。

@t = testfunc(1, 2, 3, 4); 
$x = testfunc(1, 2, 3, 4); 
sub testfunc { 
    if (wantarray) { 
     print "List context\n"; 
    } 
    # False, but defined 
    elsif (defined wantarray) { 
     print "Scalar context\n"; 
    } 
    # False and undefined 
    else { 
     print "Void context\n"; 
    } 
} 
4

有Perl編寫的函數調用wantarray返回:

  • true如果子在一個列表上下文稱爲
  • false如果標
  • undef如果兩者都不是。

舉個例子:

use strict; 
use warnings; 

sub wantarray_test { 

    if (not defined wantarray()) { 
     print "Called in void context by ", caller(), "\n"; 
    } 
    else { 
     if (wantarray()) { 
      print "Called in list context by ", caller(), "\n"; 
      return ("A", "list", "of", "results"); 
     } 
     else { 
      print "called in a scalar context by ", caller(), "\n"; 
      return "scalar result"; 
     } 
    } 

} 

my @result = wantarray_test(); 
print "@result\n"; 

my $result = wantarray_test(); 
print $result, "\n"; 

wantarray_test(); 

獎金的問題:

你覺得你會得到,如果你:

print wantarray_test(); 

你可以做,如果比這更你很喜歡Contextual::Return - 這將允許你測試更詳細的上下文,如scalar和012之間的差異。 (這很有用,例如,如果你想測試一個百分比 - 你可能不想把'0'看作'假')。

但是請注意與上下文相關的功能。建立一些意想不到的行爲是很容易的,這可能會嚴重影響你的工作。

作爲一個相關的說明 - 你不應該聲明你的子。 perl中有一個稱爲原型的機制,它定義了你的子程序期望的參數類型。請參閱:perlsub。你不應該定義你的子:

sub testfunc() 
{ 
    # some stuff 
} 

這指定了一個原型,應該避免,除非你確定這是你想要的。

+4

添加一些關於OP的糟糕原型 – ysth

+0

好點。添加。 – Sobrique

+0

哇..這真的很好。謝謝!在我的答案中添加對此的引用。 –

2

使用wantarray功能

#!/usr/bin/env perl 

use strict; 
use warnings; 
use feature 'say'; 

say my $x = testfunc(1,2,3,4); 
say my @x = testfunc(1,2,3,4); 

sub testfunc { 
    return wantarray ? @_ : "@_"; 
} 
1

詭異的命名wantarray是標準的做法 - 它可以讓你列表和標量上下文之間進行區分。您也可以使用CPAN中的Want,它比標準的wantarray內置函數稍差(請參閱Want documentation)。

下應返回相同的結果wantarray解決方案:

use Want; 
sub testfuncadelic { 
    if (want('LIST')) { 
    rreturn @_; } 
    elsif (want('SCALAR')) { 
    rreturn "@_" ; } 
    return 
} 

下應剪切並粘貼到一個shell作爲一個僞「oneliner」(Unix的語法)證明:

% cpanm Want 
% perl -MWant -E ' 
sub testfunc { 
if (want("LIST")) { 
    rreturn "array in list context ", @_;} 
elsif (want("SCALAR")) { 
    rreturn "string in scalar context @_"; } 
return } 
$result = testfunc(qw/1 2 3 4/); say $result; 
@results = testfunc(qw/1 2 3 4/); say @results;' 

輸出

string in scalar context 1 2 3 4 
array in list context 1234 

編輯

@Sobrique對這裏的標準方法有最徹底的處理 - 如果我問了這個問題,他/她會得到我的接受。我上面忽略的一件事是(如果wantarrayundef那麼顯然是'doh!),那麼你有無效的上下文!也許我假設這一點,並沒有意識到它可以明確用於檢測無效contxt。因此wantarray可以爲您提供全部三種標準調用上下文。另一方面Wanted是關於棘手的有趣的東西,我不是暗示它應該使用而是wantarray。我仍然認爲wantarray應該有一個更好的名稱:-)