语句前缀写在语句前面,并改变它们的含义、输出或运行时间。由于它们具有特定行为,因此有时它们也特定于某些语句或语句组。
lazy
§
作为语句前缀,lazy
位于任何语句之前,包括 for
循环,将执行保存到实际需要分配给它们的变量时。
my = 0;my = lazy for <1 2 3 4> ->;say ; # OUTPUT: «0»say eager ; # OUTPUT: «(0 1 2 3)»say ; # OUTPUT: «4»
$incremented
变量仅在当我们急切地评估包含延迟循环的变量 $var
时才被递增,也就是说,循环的内部部分仅在此时运行。急切性可以通过其他方式应用于变量,例如在变量上调用 .eager
方法。
my = lazy ;say ; # OUTPUT: «[...]»say .eager; # OUTPUT: «[0 1 4]»
此前缀也可以用在 gather
前面,使内部语句按需执行;一般来说,任何返回值的语句集都可以使用此方法变为按需执行。
eager
§
eager
语句前缀将急切地返回其后语句的结果,丢弃按需执行并返回结果。
my := eager gather ;say [0]; # OUTPUT: «HeyHeyHey1»
gather
在 绑定到标量时隐式按需执行。但是,使用 eager
作为语句前缀,它将在循环中运行所有三个迭代,如打印的 "Hey" 所示,即使我们只请求一行中的第一个。
hyper
§
for
循环将自动序列化其中使用的任何 HyperSeq
或 RaceSeq
;另一方面,hyper
和 race
使用(可能同时)线程来运行循环中的不同迭代
my = hyper for ^100_000
此代码比裸 for
快约 3 倍。但这里有几个注意事项
循环内的操作应该花费足够的时间才能使线程有意义。
循环内部不应该对相同的数据结构进行读写访问。让循环产生结果,并将其赋值。
如果循环内部有 I/O 操作,可能会有一些争用,所以请避免它。
hyper
和 race
之间的主要区别在于结果的顺序。如果需要循环结果按顺序产生,请使用 hyper
;如果不在乎,请使用 race
。
quietly
§
作为前缀,quietly
会抑制它之前的所有块或语句产生的运行时警告。
sub marine() ;quietly say ~; # OUTPUT: «marine»sub told-you ;quietly ;warn 'Telling you now!'; # OUTPUT: «Telling you now! [...] »
调用 code
上的 .Str
会产生警告。在代码前面加上 quietly
将只产生输出,而不会产生警告。
try
§
如果在语句前面使用 try
,它将包含其中产生的异常,并将其存储在 $!
变量中,就像 它在块前面使用时一样。
try [].pop;say $!; # OUTPUT: «Cannot pop from an empty Array..»
do
§
do
可以用作语句前缀来消除它们之前语句的歧义;例如,如果要为 for
语句的结果赋值,则需要这样做。裸 for
会失败,但这样会起作用
my = 0;my = do for ^5 ;say ; # OUTPUT: «5»say ; # OUTPUT: «(0 1 2 3 4)»
do
等同于在其他情况下用括号包围语句。它可以用作具有(可能更)直接语法的替代方案。
sink
§
与 例程的情况 一样,sink
将运行语句,丢弃结果。如果要运行一些语句以产生其产生的副作用,请使用它。
my = 0;my = sink for ^5 ;say ; # OUTPUT: «5»say ; # OUTPUT: «(Any)»
sink
语句前缀也将把 Failure
转换为异常
sub find-the-number ( Int where < 10 )for 1..^10
在这种情况下,只有当 try
块没有捕获异常时,我们才会知道该数字已被找到。
react
§
react
可用于并发程序中,以创建在发生某些事件时运行的代码块。它 与块一起工作,也可以用作语句前缀。
my Channel .= new;for ^100my = ( start react whenever ->) for ^10;startawait ;
在这种情况下,react
在 whenever
前面加前缀,这使得每次从通道读取数字时都会进行长时间的求和。