上下文和上下文器
在许多情况下,需要上下文来解释容器的值。在 Raku 中,我们将使用 context 将容器的值强制转换为某种类型或类,或者决定如何处理它,就像接收器(sink)上下文的情况一样。
Sink 上下文
Sink 相当于 void
上下文,也就是说,我们抛出(在接收器下面)操作的结果或块的返回值的上下文。通常,当语句不知道如何处理该值时,将在警告和错误中调用此上下文。
my $sub = -> $a { return $a² };
$sub; # OUTPUT: «WARNINGS:
Useless use of $sub in sink context (line 1)»
您可以使用 sink-all
方法在 Iterator 上强制使用该接收器上下文。Proc也可以通过 sink
方法沉没,迫使它们引发异常而不返回任何东西。
通常,如果在 sink 上下文中进行计算,则块将发出警告; 但是,在 sink 上下文中 gather/take 块是显式计算的,并使用 take
显式返回值。
在 sink 上下文中,对象将调用其 sink
方法(如果存在):
sub foo {
return [<a b c>] does role {
method sink { say "sink called" }
}
}
foo
# OUTPUT: sink called
Number 上下文
这个上下文,可能除了上面的所有内容之外,都是转换或解释上下文,因为它们接收无类型或类型化的变量,并将其类型化为执行操作所需的任何内容。在某些情况下,这意味着转换(例如从 Str 到 Numeric); 在其他情况下只是一种解释(IntStr 将被解释为 Int 或 Str)。
每当我们需要对变量应用数值运算时,就会调用数字上下文。
my $not-a-string="1 ";
my $neither-a-string="3 ";
say $not-a-string+$neither-a-string; # OUTPUT: «4»
在上面的代码中,只要只有几个数字而没有其他字符,字符串将在数字上下文中解释。但是,它可以具有任意数量的前导或尾随空格。
可以使用算术运算符强制数字上下文,例如 +
或 -
。在该上下文中,Numeric
将调用该方法(如果可用),并将返回的值用作对象的数值。
my $t = True;
my $f = False;
say $t+$f; # OUTPUT: «1»
say $t.Numeric; # OUTPUT: «1»
say $f.Numeric; # OUTPUT: «0»
my $list= <a b c>;
say True+$list; # OUTPUT: «4»
在列表那样的东西的情况下,数值通常等于 .elems
; 在某些情况下,像Thread 一样,它将返回唯一的线程标识符。
String 上下文
在字符串上下文中,值可以作为字符串进行操作。例如,此上下文用于强制非字符串值,以便可以将它们打印到标准输出。
put $very-complicated-and-hairy-object; # OUTPUT: something meaningful
或者当智能匹配正则表达式时:
put 333444777 ~~ /(3+)/; # OUTPUT: «「333」 0 => 「333」»
通常,将在变量上调用 Str
例程以将其上下文化; 因为这个方法是从 Mu 继承的,所以它始终存在,但并不总能保证工作。在某些核心类中,它会发出警告。
~
是(一元)字符串上下文化器。作为运算符,它连接字符串,但作为前缀运算符,它成为字符串上下文运算符。
my @array = [ [1,2,3], [4,5,6]];
say ~@array; # OUTPUT: «1 2 3 4 5 6»
当 [~]
应用于列表时,这也将在 reduction 上下文中发生:
say [~] [ 3, 5+6i, Set(<a b c>), [1,2,3] ]; # OUTPUT: «35+6ic a b1 2 3»
在那个情况下, 空列表或其它容器会字符串化为一个空字符串:
say [~] [] ; # OUTPUT: «»
由于 ~
也作为缓冲区连接运算符,因此必须检查每个元素是否为空,因为字符串上下文中的单个空缓冲区将表现为字符串,从而产生错误。
say [~] Buf.new(0x3,0x33), Buf.new(0x2,0x22);
# OUTPUT: «Buf:0x<03 33 02 22>»
然而,
my $non-empty = Buf.new(0x3, 0x33);
my $empty = [];
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also;
# OUTPUT: «Cannot use a Buf as a string, but you called the Stringy method on it
由于 ~
将字符串上下文放入此列表的第二个元素,~
将使用适用于字符串的第二个形式,从而产生所显示的错误。只需确保连接的所有内容都是缓冲区即可避免此问题。
my $non-empty = Buf.new(0x3, 0x33);
my $empty = Buf.new();
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also; # OUTPUT: «Buf:0x<03 33 02 22>»
通常,上下文会通过调用 contextualizer 将变量强制转换为特定类型; 在 mixins 的情况下,如果混合了上下文类,它将以这种方式运行。
my $described-number = 1i but 'Unity in complex plane';
put $described-number; # OUTPUT: «Unity in complex plane»
but
创建一个 mixin,它使用 Str
方法赋予复数。put
将它 Str
上下文化为一个字符串,即它调用字符串上下文,使用上面显示的结果。