Raku 谜语

A Raku Riddle

在思考 DataKinds 博文的时候,我想到了一个最奇特的谜语。它的内容如下。

命名一个东西,当它被移除时,它仍然被定义,但从未存在过。

答案是一个 Array 元素,据此 Array 得到了默认值。

my @a is default('fill') = 1,2,3;
say @a[5]:exists; # False
@a = @a[5]:delete;
say @a[5].defined; # True
say @a[5]:exists; # False

有多少元素得到了这样一个 Array,迭代何时结束?

say @a.elems; # 3
.print for @a; # 123

它有3个元素,我们可以对它们进行迭代。什么是完全合理的。但是,如果我们根据循环的定义性来判断,它将是无限的。

while @a[$++] -> $_ { .say } # will not stop

那么这是一个无限的列表吗?它不能用完元素,所以如果我们相信关于 infix:<Z>文档,它应该不会停止 zip。

my @a is default('‽') = 1,2,3;
my @b = <a b c d e>;

say @a Z @b;
# OUTPUT: ((1 a) (2 b) (3 c))

我试图说服 Z 按照期望的方式行事,但无济于事。在这个过程中,我学会了如何在容器声明后很久才设置它的默认值。

my @a := Array.new;
{
    use nqp;
    my $descriptor = nqp::getattr(@a.VAR, Array, '$!descriptor');
    my $a = $descriptor.set_default('‽');
}
say @a[1];
# OUTPUT: ‽

Rakudo 用迭代器做了很多事情。由于它们是一个实现细节,我们不能轻易建立自己的。这并不是一个真正的问题,因为 zip 操作符足够聪明,可以 DWIM。

my @a = 1,2,3;
my @b = <a b c d e>;
say ((|@a, |('‽' xx *)) Z (|@b, |('‽' xx *)))[^(@a.elems max @b.elems)];
# OUTPUT: ((1 a) (2 b) (3 c) (‽ d) (‽ e))

我相信这就是 DataKinds 要找的东西。

by glfdex.

comments powered by Disqus