在 Raku 开发过程中,新特性通常在设计完成之前作为实验性特性提供给用户。最终,这些特性可能会成为 Raku 规范的一部分。要使用这些特性,请在程序源代码中使用 experimental 编译指示,例如,如下所示

use experimental :macros;

这些是目前处于实验阶段的特性。

pack§

Pack 是一种允许对一般数据结构进行二进制序列化的特性,它继承自 Perl 的 packpack 顺序通过使用打包字符串以特定方式打包数据结构来创建 Buf,打包字符串的选项在 unpack 的描述中 显示。您可以在程序开头插入此编译指示来启用它

use experimental :pack;

例如,我们可以将数字打包为十六进制 (H),并重复该模式,直到没有更多元素 (*)

use experimental :pack;
say pack("H*""414243").contents;#  OUTPUT: «(65 66 67)␤» 

有一个对应的 unpack 例程,它执行完全相反的操作。

use experimental :pack;
my $buf=Buf.new(65,66,67);
say $buf.unpack("H*"); # OUTPUT: «414243␤» 

并非所有上述符号都保证实现,路线图中也不包括退出该阶段的固定日期。

另请参阅 packunpack 的文档,位于 Blob 页面。

macros§

是代码生成例程,它们在编译时生成代码,即程序执行之前。在 Raku 中,它的使用仍然是实验性的,需要通过 pragma 启用

use experimental :macros;

宏处理发生在解析时间。宏生成一个抽象语法树,该树被移植到程序语法树中。quasi 是执行此任务的例程。

use experimental :macros;
macro does-nothing() {
    quasi {}
};
does-nothing# OUTPUT: «» 

宏是一种例程,因此它们可以以完全相同的方式接受参数,并且几乎以相同的方式起作用。

use experimental :macros;
macro is-mighty$who ) {
    quasi { "$who is mighty!"}
};
say is-mighty "Freija"# OUTPUT: « "Freija" is mighty!␤» 

“几乎”说明了参数被插入为字面量,包括引号。请注意,我们也可以按照与例程相同的规则,为宏调用消除括号。您可以使用取消引用结构 {{{}}} 来摆脱这种事情

use experimental :macros;
macro is-mighty$who ) {
    quasi { {{{$who}}} ~ " is mighty!"}
};
say is-mighty "Freija";  # OUTPUT: «Freija is mighty!␤» 

由于宏扩展发生在解析时,因此在宏中使用外部变量时必须小心

use experimental :macros;
my $called;
macro called() {
    $called++;
    quasi { "Called" }
};
say called() ~ " $called times";
say called() ~ " $called times"# OUTPUT: «Called 2 times␤Called 2 times␤» 

由于宏在解析时扩展,因此 $called 将在运行时开始时成为结果,即已经为 2,如打印所示。但是,用 0 初始化 $called 将使它打印 Called 0 times,因为该初始化在解析阶段之后运行,此时宏已扩展。

当需要进行复杂的计算初始化时,宏非常有用。但是,它们仍然处于实验阶段是有充分理由的。虽然上面显示的功能不太可能改变,但任何事情,甚至它们的存在本身,都可能随时根据需要而改变,因此最好将它们远离生产代码。同时,看看 Masak 的这篇文章 以及 007(一种新的宏语言)可能会让你对未来有所了解。

cached§

以下 pragma

use experimental :cached;

启用 is cached 特性,该特性存储例程调用的结果,如果使用相同的参数调用,则返回相同的值。

当涉及大量计算时,它可以被使用,例如这个使用 亲和数 的示例,取自 2018 年的降临日历

use experimental :cached;
 
sub aliquot-parts$number ) is cached {
    (^$number).grep: $number %% *;
}
 
sub infix:<amic>$m$n ) {
    $m == aliquot-parts($n).sum &&
    $n == aliquot-parts($m).sum;
}
 
# Taken from https://en.wikipedia.org/wiki/Amicable_numbers 
my @numbers = [2620292450205564623263686692866992];
 
say "Aliquot parts of $_ are "aliquot-parts $_ for @numbers;
 
for @numbers X @numbers -> @pair {
    say "@pair[0] and @pair[1] are ",
        @pair[0amic @pair[1]??" "!!"not ""amicable";
}

此代码缓存了商数部分的计算,因此当调用 amic 运算符时,它只计算一次;事实上,第一个打印这些商数部分的循环将是唯一真正执行计算的循环。

另请参阅 该特性的描述,以获取更多信息和示例。

注意:此功能不是线程安全的。

rakuast§

pragma

use experimental :rakuast;

使 RakuAST 包及其类可用于6.e之前的语言版本中。