Wait the light to fall

给自己做个礼物

焉知非鱼

making myself a present

我最后一个简单的圣诞愿望,结果却相当复杂。在实际代码中测试一个想法,可以发现很多改变 CORE 概念所产生的问题。幸运的是,我们可以在 Raku 中调整很多东西,而不需要改变 Rakudo 中的代码。有一件事一直困扰着我,那就是复合类型的 Mixins。当混入一个值时,这个值会被一个与值的类型对象名称相同的方法暴露出来。

my $a = "foo" but %{ bar => 42 };
say $a.Hash<bar>;
# OUTPUT: 42

这是对的,但不是很 DWIMy。事实证明,我们不需要做太多改变。

multi sub infix:<but>(Mu \l, Associative \h) {
    constant &BUT = &infix:<but>;
    role MixinAssociative[%h, \v] does Associative {
        has $.the-value = v;
         has %.the-hash handles<AT-KEY EXISTS-KEY DELETE-KEY push iterator list kv keys values> = %h;
    }

    BUT(l, MixinAssociative[h, l]);
}

my $a = "foo" but %{ bar => 42 };
say $a<bar>;
# OUTPUT: 42

我需要把原来的 &infix:<but> 藏起来,避免无限递归。在 Mixin 上对 raku 的任何调用都不能真正说明全部问题。

my $a = "foo" but %{ bar => 42 };
dd $a;
# OUTPUT: Str+{<anon|1>} $a = "foo"

通过在 MixinAssociative 中提供我们自己的 raku 方法,我们可以说出真相。

...
method raku( --> Str ) {
    $!the-value.raku ~ " but " ~ %.the-hash.raku
}
...

my $a = "foo" but %{ bar => 42 };
dd $a;
# OUTPUT: Str+{MixinAssociative[Hash,Str]} $a = "foo" but {:bar(42)}

改变值的 Mixins 的语义将是对语言相当大的改变。在 Mixins 上有更好的 raku 方法则不会。然而,在 Roast 中可能会有落差。这很好地表明,还有很多想法可以探索,希望能改进一门已经很好的语言。