is Block
Routine
是一个代码对象,适用于大于 Block
的代码单元。Routine 是 Sub
(以及运算符)和 Method
的公共超类,这两个主要代码对象用于代码重用,以及 Macro
和 Submethod
。
Routine 充当 return
的作用域限制器(即 return
从最内层外部 Routine 返回)。
Routine 级别也是处理 多重性(多重子例程和多重方法)的级别。子例程还可以声明为 anon
。有关更多信息,请参阅 anon
声明符的文档。
Routine 是 Code
层次结构中最低级的对象,它可以通过自动定义且包含相应 Routine
对象的 &?ROUTINE
变量 进行自省。
;say Foo.bar; # OUTPUT: «Submethod»
方法§
方法名称§
method name(Routine: --> Str)
返回子例程或方法的名称。
方法包§
method package(Routine:)
返回定义例程的包。
方法多重§
method multi(Routine: --> Bool)
如果例程是多重子例程或方法,则返回 True
。请注意,多重子例程的名称引用其 proto
,如果对其调用此方法,则此方法将返回 false。需要在候选本身上调用它
multi foo ($, $) ;say .multi; # OUTPUT: «False»say .candidates».multi; # OUTPUT: «(True)»
方法候选§
method candidates(Routine: --> Positional)
返回多重候选列表,或者如果它不是多重候选,则返回一个包含它自己的单元素列表
方法 cando§
method cando(Capture )
返回一个候选列表,该列表可以与给定的 Capture
一起调用,按最窄的候选优先的顺序排列。对于方法,Capture 的第一个元素需要是调用者
.signature.say for "foo".^can("comb")[0].cando: \(Cool, "o");# OUTPUT: «(Cool $: Str $matcher, $limit = Inf, *%_)»
方法 wrap§
method wrap(Routine: )
包装(即就地修改)例程。这意味着对该例程的调用首先调用 &wrapper
,然后 &wrapper
可以(但不一定)使用 callsame
、callwith
、nextsame
和 nextwith
调度程序调用原始例程。例程的返回值也是包装器的返回值。
wrap
返回一个名为 Routine::WrapHandle
的私有类的实例,您可以将其传递给 unwrap 以还原原始例程。
方法 unwrap§
method unwrap()
在用 wrap 包装后还原原始例程。虽然签名允许传递任何类型,但只有 wrap
返回的 Routine::WrapHandle
类型才能有效使用。
方法 is-wrapped§
method is-wrapped()
返回 True
或 False
,具体取决于 Routine
是否被包装。
方法 yada§
method yada(Routine: --> Bool)
如果例程是存根,则返回 True
say (sub f() ).yada; # OUTPUT: «True»say (sub g() ).yada; # OUTPUT: «False»
特性 is cached§
multi trait_mod:<is>(Routine , :!)
导致例程的返回值被存储,以便在使用相同参数列表进行后续调用时,可以立即返回存储的值,而不是重新运行例程。[1]
当存储和返回计算值比每次重新计算它快得多时,并且节省的时间超过使用更多内存的成本时,这很有用。
即使传递给例程的参数是“引用类型”(例如对象或数组),那么出于缓存的目的,它们也只会根据其内容进行比较。因此,在这种情况下,第二次调用将命中缓存
say foo( [1, 2, 3] ); # runs foosay foo( [1, 2, 3] ); # doesn't run foo, uses cached value
由于它仍处于实验阶段,因此您必须在使用它的任何模块或脚本中插入 use experimental :cached;
语句。
use experimental :cached;sub nth-prime(Int where * > 0) is cachedsay nth-prime(43);say nth-prime(43);say nth-prime(43);
生成此输出
Calculating 43th prime 191 191 191
注意:此功能不是线程安全的。
特性 is pure§
multi trait_mod:<is>(Routine , :!)
将子例程标记为纯,即断言对于相同的输入,它将始终产生相同输出,而没有任何其他副作用。
is pure
特性是程序员对编译器的承诺,即当在编译时知道参数时,它可以对这些函数的调用进行常量折叠。
sub syllables() is pure
即使函数在特殊情况下引发异常或修改临时对象,您也可以将函数标记为纯函数;因此,is pure
特性可以涵盖编译器无法自行推断的情况。另一方面,您可能不想对生成较大返回值的函数(例如字符串或列表重复运算符、中缀 x
和 xx
)进行常量折叠,即使它们是纯函数,以避免生成较大的预编译文件。
要使用特定编译器查看它的操作,您可以尝试此示例
BEGINsay ‘Start’;say (^100).map: ;# Example output:# Begin# Generating syllables# Start# (matiroi yeterani shoriyuru...
从本质上讲,这允许编译器在编译时执行一些操作。常量折叠的好处可能包括更好的性能,尤其是在折叠代码已预编译的情况下。
此外,在汇入上下文中使用纯函数或运算符(即,结果被丢弃)可能会导致警告。代码
sub double() is pure ;double(21);say "anything";# WARNING: «Useless use of "double(21)" in expression "double(21)" in sink context (line 2)»
如果您想将此特性应用于 multi
,则需要将其应用于 proto
;否则它将不起作用,至少在 2018.08 及更低版本中。
特性是 rw§
multi trait_mod:<is>(Routine , :!)
当一个例程使用此特性进行修改时,其返回值将可写。这在返回变量或哈希或数组的可写元素时很有用,例如
sub walk(\thing, *) is rwmy ;walk(, 'some', 'key', 1, 2) = 'autovivified';say .raku;
产生
("some" => ).hash
请注意,return
将返回值标记为只读;如果您需要从is rw
例程中提前退出,则必须使用 return-rw
。
特性是 export§
multi trait_mod:<is>(Routine , :!)
将例程标记为导出到世界其他地方
import Foo; # makes sub double availablesay double 21; # 42
在另一个文件内部,您会说 use Foo;
来加载模块并导入导出的函数。
有关更多详细信息,请参见 导出和选择性导入模块。
特性是 DEPRECATED§
multi trait_mod:<is>(Routine , :!)
将Routine
标记为已弃用;也就是说,它不应该再继续使用,并最终将被移除。可以指定一个可选消息来指定替换功能
通过同时提供原始(已弃用)和新的Routine
,您可以避免在单个版本中发生重大更改,方法是允许用户有时间和说明来更新其代码。仅在至少包含警告和新Routine
的一个版本后才删除已弃用的版本。
此代码
sub f() is DEPRECATED('the literal 42')say f();
生成此输出
42 Saw 1 occurrence of deprecated code. ================================================================================ Sub f (from GLOBAL) seen at: deprecated.raku, line 2 Please use the literal 42 instead. -------------------------------------------------------------------------------- Please contact the author to have these occurrences of deprecated code adapted, so that this message will disappear!
特性是 hidden-from-backtrace§
multi trait_mod:<is>(Routine, :!)
隐藏例程,使其不显示在默认回溯中。例如
sub inner ;sub outer ;outer();
产生错误消息和回溯
OH NOEZ in sub inner at bt.raku:1 in sub outer at bt.raku:2 in block <unit> at bt.raku:3
但如果inner
标记为hidden-from-backtrace
sub inner is hidden-from-backtrace ;sub outer ;outer();
错误回溯不会显示它
OH NOEZ in sub outer at bt.raku:2 in block <unit> at bt.raku:3
特性是 default§
multi trait_mod:<is>(Routine , :!)
有一个针对Routine
的特殊特性,称为is default
。此特性旨在作为消除歧义multi
调用的方式,而这些调用通常会引发错误,因为编译器不知道使用哪一个。这意味着,给定以下两个Routine
,将调用具有is default
特性的那个。
multi f() is defaultmulti f()f(); # OUTPUT: «"Hello there"»
is default
特性对于调试和其他用途非常有用,但请记住,它只会解决两个具有相同优先级的Routine
之间的歧义分派。如果其中一个Routine
比另一个窄,则将调用该Routine
。例如
multi f() is defaultmulti f(:)f(); # "Use of uninitialized value $greet..."
在此示例中,调用了没有is default
的multi
,因为它实际上比带有它的 Sub
更窄。
特性是 raw§
multi trait_mod:<is>(Routine , :!)
完全访问例程返回的数据结构。
my = <zape zapatilla>;sub þor() is raw;þor()[1] = 'pantuflo';say ; # OUTPUT: «[zape pantuflo]»
trait 是 test-assertion§
multi trait_mod:<is>(Routine, :!)
声明一个例程生成测试输出(又名 TAP)。当报告失败时,将使用调用例程的位置,而不是此例程。例如
use Test;sub foo-test() is test-assertionfoo-test(666); # <-- error is reported on this line