perl wantarray 函数
2019-06-14 12:40:16 阿炯

wantarray是一个非常典型的perlish函数,针对不同的上下文返回不同的值。

Returns true if the context of the currently executing subroutine or eval is looking for a list value. Returns false if the context is looking for a scalar. Returns the undefined value if the context is looking for no value (void context).

说明

根据函数被赋值的类型(是列表还是标量),返回不同的值:
当不对定义的函数的返回值赋值时,wantarray返回undef;
当把定义的函数的返回值进行赋值,赋值给标量的时候,wantarray返回空字符串(空字串与undef不同);
当把定义的函数的返回值进行赋值,赋值给列表的时候,wantarray返回1;

如果当前正在执行的子过程在寻找列表数值,那么此函数返回真,否则返回假。如果调用环境需要的是一个标量,那么该函数返回一个定义了的假(""),而如果调用环境并不需要任何东西,(也就是说空环境)那么返回一个未定义的假值(undef);

下面是它的典型用法的例子:
return unless defined wantarray;#不需要干什么事情
my @a = complex_calculation();
return wantaray ? @a : \@a;

###############################
sub foo {
   return(wantarray() ? qw(A, B, C) : '1');
}
$result = foo();    # scalar context
@result = foo();    # array context

print("foo() in a  scalar context:$result\n");
print("foo() in an array  context:@result\n");

运行后的结果:
foo() in a  scalar context:1
foo() in an array  context:A, B, C


又见 caller。这个函数真是应该命名为"wantlist",但是我们是在列表环境还叫数组环境的时候命名它的(译注:数组英文词是"array",列表英文词是"list") 。

#定义函数
sub wantarray_example{ # defined wantarray 判断函数的返回值是否进行赋值了
if(defined wantarray){
    print "assignment!\n";
}else{
    print "no assignment!\n";
}# wantarray 判断函数的返回值赋值给变量的类型,如果是列表,则返回1,否则返回undef
if(wantarray){
    print "It is List!\n"; return qw/1 2 3 4/;
}else{
    print "It is Scalar!\n"; return "A";
}
}

#调用函数
#不对函数的返回值进行赋值
print "======example1======\n";
wantarray_example();

#对函数的返回值进行赋值,但是赋值给一个列表
print "======example2======\n";
my @list = wantarray_example();

#对函数的返回值进行赋值,但是赋值给一个标量
print "======example3======\n";
my $scalar = wantarray_example();

# 将存贮在变量中的值打印出来
print "======print value======\n";
print "LIST  : @list\n";
print "SCALAR: $scalar\n";

最后运行结果为
======example1======
no assignment!
It is Scalar!
======example2======
assignment!
It is List!
======example3======
assignment!
It is Scalar!
======print value======
LIST  : 1 2 3 4
SCALAR: A

从结果中可以得到

把函数结果进行赋值给列表,wantarray返回1,否则(赋值给标量或者不赋值),wantarray返回undef。可是在defined那里,发现当赋值给标量的时候,defined wantarray好像返回的是1。

======example3======
assignment!
It is Scalar!

就是这里,为了证实 wantarray 和 defined wantarray 的返回值,再运行下列代码:

#定义函数
sub wantarray_example{
    print "*",wantarray,"*","\n";
    print "*",defined wantarray,"*","\n";
}

print "====NO ASSIGN====\n";
wantarray_example();
print "====SCALAR====\n";
my $scalar = wantarray_example();
print "====LIST====\n";
my @list = wantarray_example();

结果为
====NO ASSIGN====
**
**
====SCALAR====
**
*1*
====LIST====
*1*
*1*

可以看到在将函数的返回值赋值给标量那里,wantarray的值和defined wantarray不对应。说明当把函数的结果赋值给标量的时候wantarray的返回值不是undef,也不是0,而是空字符串。何以见得呢?

再次运行下列代码
my $value1 = undef;# undef
my $value2 = 0;# 0
my $value3 = "";# 空字符串

# 先打印出对应的defined的值
print "======defined======\n";
print "*",defined $value1,"*","\n";
print "*",defined $value2,"*","\n";
print "*",defined $value3,"*","\n";

# 再打印出变量本身的值
print "======self======\n";
print "*",$value1,"*","\n";
print "*",$value2,"*","\n";
print "*",$value3,"*","\n";

结果为
======defined======
**
*1*
*1*
======self======
**
*0*
**

得到结论

当不对定义的函数的返回值赋值时,wantarray返回undef;
当把定义的函数的返回值进行赋值,赋值给标量的时候,wantarray返回空字符串(空字串与undef不同);
当把定义的函数的返回值进行赋值,赋值给列表的时候,wantarray返回1;

所以将刚开始的代码改成这样,就能很好的说明问题了。

# 定义函数
sub wantarray_example{
# 判断函数的返回值是否进行赋值了
if(defined wantarray){
    print "assignment!\n";
}else{
    print "no assignment!\n";
}
#判断函数的返回值赋值的类型
if(wantarray){
    print "It is List!\n";
    return qw/1 2 3 4/;
}elsif(defined wantarray){
    print "It is Scalar!\n";
    return "A";
}else{
    print "It is BLANK!\n";
}
}

#调用函数

#不对函数的返回值进行赋值
print "======example1======\n";
wantarray_example();

#对函数的返回值进行赋值,但是赋值给一个列表
print "======example2======\n";
my @list = wantarray_example();

#对函数的返回值进行赋值,但是赋值给一个标量
print "======example3======\n";
my $scalar = wantarray_example();

# 将存贮在变量中的值打印出来
print "======print value======\n";
print "LIST  : @list\n";
print "SCALAR: $scalar\n";

结果为
======example1======
no assignment!
It is BLANK!
======example2======
assignment!
It is List!
======example3======
assignment!
It is Scalar!
======print value======
LIST  : 1 2 3 4
SCALAR: A

那么这个函数就变得灵活多变了,可以根据上下给出不同的返回值!

wantarray()'s result is unspecified in the top level of a file, in a BEGIN , UNITCHECK , CHECK , INIT or END block, or in a DESTROY method.

参考来源:

perl中的wantarray()函数

wantarray - returning list or scalar based on context