外层序列算子可以理解为:以2和3开始序列,然后运行block中的代码,计算出下面的每一个值,一直到无穷大。
序列运算符将传递该块所需的尽可能多的参数。例如,斐波那契数列表示为1, 1, * + * ... Inf,其中* + * 是lambda -> $a, $b { $a + $b } 的简写;由于这需要两个参数,因此它将被赋予序列中的前两个值。
当我们在一个块中使用@_ 时,就好像我们写了一个像-> *@_ { } 这样的lambda,这是一个slurpy。当与... 一起使用时,表示我们希望传递所有序列中之前的值。
子first 接受一个谓词(我们评估返回真或假的东西)和一个要搜索的值列表,并返回与谓词匹配的第一个值。 (阅读此类内容的提示:每当我们调用 function-name arg1, arg2 时,我们总是会解析参数的术语,这意味着我们知道 * 在这里不能是乘法运算符。)
我们给first 的谓词是* %% none(@_)。这是一个闭包,它接受一个参数并检查它是否可以被序列中的任何先前值整除 - 因为如果是,它就不可能是素数!
接下来,@_[* - 1], * + 2 ... Inf,是要搜索的值序列,直到我们找到下一个素数。这采取以下形式:第一个值,如何获得下一个值,并一直持续到无穷大。
第一个值是我们找到的最后一个素数。再一次,* - 1 是一个闭包,它接受一个参数并从中减去 1。当我们将代码传递给数组索引器时,它会使用元素的数量来调用。因此,@arr[* - 1] 是 Raku 习语,表示“数组中的最后一件事”,@arr[* - 2] 是“数组中倒数第二个”,等等。
* + 2 计算序列中的下一个值,它是一个闭包,它接受一个参数并将其加 2。虽然我们实际上可以只做一个简单的范围 @_[* - 1] .. Inf 并得到正确的结果,但检查所有偶数是很浪费的,因此 * + 2 可以产生一个奇数序列。
所以,直观地说,这一切都意味着:下一个素数是第一个(奇数)值,之前的素数都没有分成。