标量或数组函数

时间:2015-04-20 14:29:51

标签: arrays perl function scalar

我必须执行将作为标量和数组工作的函数。例如:

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

有人知道我该怎么做吗? 它必须打印"标量"如果它是$ x并且打印"数组"如果@t。我试着做这样的事情:

sub testfunc()
{
   print "test";
}

但即使这样也行不通:/

4 个答案:

答案 0 :(得分: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";
    }
}

答案 1 :(得分: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,你可以做更多的事情 - 这将允许你测试更详细的背景,例如scalarboolean之间的差异。 (这很有用,例如,如果你想测试一个百分比 - 你可能不想把'0'视为'假')。

但请注意上下文敏感的功能。构建一些意想不到的行为很容易,这可能会让你严重受挫。

作为相关说明 - 您不应该按照您的方式声明您的子。 perl中有一种称为原型的机制,用于定义子例程所期望的参数类型。见:perlsub。您不应将sub定义为:

sub testfunc() 
{   
     # some stuff
}

这指定了一个原型,应该避免,除非你确定这是你想要的。

答案 2 :(得分: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 ? @_ : "@_";
}

答案 3 :(得分: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在这里对标准方法有最彻底的处理 - 如果我问过这个问题,他/她会接受我的接受。我忽略的一件事是(显然,&#39; doh!)如果wantarrayundef那么你就有了无效的背景!也许我假设这个并没有意识到它可以被明确地用于检测void contxt。因此wantarray可以为您提供所有三个标准调用上下文。另一方面,Wanted是关于棘手的有趣的东西,我并不是故意暗示它应该用{em>代替 wantarray。我仍然认为wantarray应该有一个更好的名字: - )