上下文解释容器的值。在 Raku 中,我们使用活动上下文将容器的值强制转换为类型或类,或者决定如何处理它(参见 sink)。通常,接收对象的上下文将在必要时通过隐式调用其上的特定方法来强制转换该对象。

汇聚§

sink 上下文等同于其他语言中的 void 上下文。它是一个对任何代码的结果或返回值都不做任何处理的上下文:一个术语、一个操作或一个代码块。通常,当此上下文使用一个值或变量时,会发出警告或错误,因为该值被忽略了。sink 的助记符与摆脱某物有关:水流入水槽的排水管;船只沉没;散热器去除热量。

my $sub = -> $a { $a² };
$sub# OUTPUT: «WARNINGS:␤Useless use of $sub in sink context (line 1)␤» 

你可以使用 sink-all 方法,在 Iterator 上强制使用 sink 上下文。 Proc 也可以 通过 sink 方法被 sink,强制它们抛出异常,而不是返回任何东西。

大多数代码块在 sink 上下文中评估时会发出警告;但是,gather/take 代码块 在 sink 上下文中显式评估,使用 take 显式返回的值。

my @results = gather for 1..1 { ^10 .map: *.take };
say @results# OUTPUT: «[0 1 2 3 4 5 6 7 8 9]␤» 

在这个例子中,for 在 sink 上下文中运行,在它内部,map 也是。结果通过 gather/take 从循环中显式获取。

在 sink 上下文中,一个对象如果存在 sink 方法,将调用它。

sub foo {
    return [<a b c>does role {
        method sink { say "sink called" }
    }
}
foo# OUTPUT: «sink called␤» 

数字§

这个上下文,以及可能除了上面的 sink 之外的所有其他上下文,都是 转换解释 上下文,因为它们接受一个无类型或有类型的变量,并将其鸭子类型化为执行操作所需的任何类型。在某些情况下,这意味着转换(例如,从 StrNumeric);在其他情况下,只是解释(IntStr 将被解释为 IntStr)。

数字上下文 在我们需要对一个变量应用数值操作时被调用。

my $stringone = "1                 ";
my $stringthree = "3                        ";
say $stringone + $stringthree# 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␤» 
say +"  \n ";     # OUTPUT: «0␤» 

任何数量的空格都将转换为 0,如最后一个语句所示。对于 列表 类的东西,数值通常等同于 .elems;在某些情况下,例如 线程,它将返回一个唯一的线程标识符。

字符串§

字符串上下文 中,值可以作为字符串进行操作。例如,此上下文用于强制非字符串值,以便它们可以打印到标准输出。

put $very-complicated-and-hairy-object# OUTPUT: something meaningful 

或者当与正则表达式进行智能匹配时

put 333444777 ~~ /(3+)/# OUTPUT: «333␤»

通常,Str 例程 将在变量上调用以对其进行上下文化;由于此方法是从 Mu 继承的,因此它始终存在,但不能保证始终有效。在某些核心类中,它会发出警告。

~ 是(一元)字符串上下文化器。作为运算符,它连接字符串,但作为前缀运算符,它成为字符串上下文运算符。

my @array = [ [1,2,3], [4,5,6]];
say ~@array# OUTPUT: «1 2 3 4 5 6␤» 

这也会发生在 归约 上下文中,当 [~] 应用于列表时

say [~] [ 35+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(0x30x33);
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(0x30x33);
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>␤» 

通常,上下文会通过调用上下文化器将变量强制转换为特定类型;在混合类的例子中,如果上下文类被混合进来,它将以这种方式表现。

my $described-number = 1but 'Unity in complex plane';
put $described-number# OUTPUT: «Unity in complex plane␤»

but 创建了一个混合类,它赋予复数一个 Str 方法。put 将其上下文化为字符串,也就是说,它调用 Str,即字符串上下文化器,并显示上面的结果。

布尔值§

此上下文将强制变量被解释为 TrueFalse

say "Hey" if 7;  # OUTPUT: «Hey␤» 
say "Ahoy" if "";

此上下文出现在诸如 ifwhile 之类的表达式中,等同于对这些值调用 so

say "Hey" if 7.so;          # OUTPUT: «Hey␤» 
say "Ahoy" if not set().so# OUTPUT: «Ahoy␤» 

一般来说,非零非空将被转换为True;零或空将等同于False。但.so可以被定义为返回我们想要的任何布尔值,所以这只是一个经验法则。

布尔上下文运算符?和否定布尔上下文运算符!将强制对对象进行布尔上下文。

say ? 0i;    # OUTPUT: «False␤» 
say ! :true# OUTPUT: «False␤» 

列表§

实际上有几种不同的列表上下文,在该页面中有更好的解释。一般来说,列表上下文化器是逗号,

say (3,).^name# OUTPUT: «List␤»

在这种情况下调用的方法也是.list

Any.list.^name;   # OUTPUT: «List␤» 
say 3.list.^name# OUTPUT: «List␤» 
say (^3).list;    # OUTPUT: «(0 1 2)␤» 

项目上下文§

项目或标量上下文将把复杂的数据片段视为单个项目。当您尝试将数据分配给标量变量时,它会被强制。

my $scalar-context = <1 2 3>;
say "→ $_" for $scalar-context# OUTPUT: «→ 1 2 3␤» 

它可以使用$运算符来诱导,该运算符充当上下文化器运算符,通过调用item作为方法或例程。

.say for $(1,2,3);      # OUTPUT: «(1 2 3)␤» 
.say for (1,2,3).item;  # OUTPUT: «(1 2 3)␤» 
.say for item1..3 );  # OUTPUT: «1..3␤» 

项目化只影响它们在列表上下文中的行为;但是,它们仍然会保留它们的Positional角色或它们可能具有的其他角色。

$(1,2,3).elems.say;          # OUTPUT: «3␤» 
say (1,2,3).item[2];         # OUTPUT: «3␤» 
say $key => 'value')<key># OUTPUT: «value␤» 

项目化容器化数据结构中的值,例如,防止它们被扁平化到周围的列表或数据结构中。

.say for (1$(2,3), 4).flat# OUTPUT: «1␤(2 3)␤4␤» 
say (1$<a b>2).elems# OUTPUT: «3␤» 

项目化运算符将调用对象上的.item方法;它也可以作为子例程调用。由于这是从Mu继承的方法,因此任何类的对象都可以被项目化。