Iterating Past the Finish

楽土

前段时间有人提出如何增强(augment) Any问题。事实证明,增强部分是有效的,但新增加的方法并没有传播给内置类型的子类型。可以通过对所有类型对象调用 .compose 来强制传播。用 .^mro 获取所有父类的列表,用 进行检查。

augment class Cool { method HTML { HTML.new(self) } }
if Cool ∈ T.HOW.mro(T) { T.HOW.compose(T); }

我踩到了一条龙

棘手的是要得到所有预定义的类。主要是因为 core:: 里有很多东西连调用方法的接口都没有实现。我们可以调用 .DEFINITE,因为那不是方法。所以我们可以剔除所有预定义的对象,剩下的就是类型对象和从 NQP 泄漏到 Perl 6 领域的东西。那些野兽并没有实现 .mro,所以通过 try 的保护,我们可以得到一个所有 Perl 6 类型对象的列表。这些类型对象包含 IterationEnd。因此,我们不能相信 for 或其他任何使用迭代器来循环一个 list 的东西。列表中也有 Slip。我们可以通过到处使用绑定来帮助。

my @a = CORE::.values;
my @types;
for 0..^@a.elems -> $i {
  my \T := @a[$i];
  try @types[$++] := T if not T.DEFINITE;
}

for 0..^@types.elems -> $i {
  my \T := @types[$i];
  try if Cool ∈ T.HOW.mro(T) {
    T.HOW.compose(T);
  }
}

就这样,我们有了。所有"酷"的孩子们都被重新组成(.composed)了。

这不是魔术!

我学到了一些东西。首先,Perl 6 背后的很多魔法都只是类型检查。任何处理列表迭代或类似构造的东西都是检查 SlipIterationEnd,并分支处理它们的特殊性质。

其次,有很多接口渗入了规范领域,而这些接口在那里是没有任何作用的。我担心这可能会在以后咬住我们,因为任何有用的接口迟早会被程序员滥用。我更希望 Rakudo 的内部运作能够很好的隐藏起来。

我找到了一个处理令人苦恼的内置类型的方法,所以在核心开发人员修复这个 bug 之前不会太久。

by gfldex.

comments powered by Disqus