我有一个函数,它依赖于调用上下文,我想使用此函数作为其他函数的参数.令人惊讶的是,我发现second现在在列表上下文中调用此函数.我尝试强制标量上下文+()但它不能像我预期的那样工作.所以唯一的方法就是隐含地调用它scalar.
use 5.010;
say first( 1, second( 'y' ) );
say first( 1, +( second( 'y' ) ) );
say first( 1, scalar second( 'y' ) );
sub first {
my $x = shift;
my $y = shift;
return "$x + $y";
}
sub second {
my $y = shift;
if ( wantarray ) {
qw/ array array /;
} else {
'scalar';
}
}
__END__
1 + array
1 + array
1 + scalar
Run Code Online (Sandbox Code Playgroud)
函数的参数被视为列表,但它是否意味着该列表中的每个参数也都意味着列表上下文?如果是,那为什么呢?
并且,使用scalar作品,但我还有其他方法在标量上下文中调用此函数(没有中间变量)?
在列表上下文中评估函数参数是有意义的:
在Perl中,所有子例程都将列表映射到列表.
如果一个子获取一个列表,那么评估列表上下文中的所有参数是有意义的,这使得函数可以组合.考虑map:
map { ... } 1, 2, 3; # makes sense
map { ... } foo(); # can we "return 1, 2, 3" for the same effect?
Run Code Online (Sandbox Code Playgroud)
如果foo()在标量上下文中调用,这将等同于return 3我们打算返回列表时1, 2, 3.使用列表上下文使我们能够在没有许多显式循环的情况下组成列表转换.在使用Schwartzian转换就是一个最好的例子:
my @sorted =
map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [make_key($_), $_] }
@input;
Run Code Online (Sandbox Code Playgroud)有两种方法可以在列表上下文中评估参数:
使用强制标量上下文的表达式,如scalar标量操作.
使用类似的原型($).这破坏了函数的可组合性,要求您的子例程预先声明,可能具有令人困惑的语义,并且是远距离的动作.因此应避免使用原型.
你+(...)没有强制标量上下文,因为一元加上不强加上下文.它通常用于消除函数应用程序中的parens(例如用于优先级),例如map +($_ => 2*$_), 1, 2, 3.
一元加号与二进制加号不同,后者是一个算术运算符,它对其操作数施加标量上下文并将它们强制转换为数字.
为什么函数参数会引发列表上下文?
子例程接受可变数量的标量作为参数。还有什么其他选择呢?
函数的参数被视为列表,但这是否意味着该列表中的每个参数也暗示列表上下文?如果是,那为什么?
是的。因为您希望能够根据哈希和数组的内容构建列表。有一百万个理由说明它有用。
%h = (%h, ...); # Add to a hash
f( $x, @opts ); # Composing argument lists
etc
Run Code Online (Sandbox Code Playgroud)
using
scalar有效,但是我必须在标量上下文中调用此函数(没有中间变量)还有哪些其他方法?
有点。
say first( 1, "".second( 'y' ) ); # Side-effect: stringification
say first( 1, 0+.second( 'y' ) ); # Side-effect: numificatiion
say first( 1, !!second( 'y' ) ); # Side-effect: conversion to boolean
Run Code Online (Sandbox Code Playgroud)
子程序原型也可以强制标量上下文,但正是因为这个原因,它们通常被认为是不好的。