感觉像一个 bug

It felt like a bug

IO::Path 提供了不少关于文件的信息。缺少的是它的真实类型。文件的结尾是有欺骗性的。在文件的操作系统上,我们可以得到一个清晰的图像。Shelling 用 file -b -i 获取 mimetype 有点慢,所以我试着在文件名列表上添加一个 .hyper.map,并混入一个角色到 IO::Path。我踩到了一些感觉像 bug 但又不是的东西。以下是 golfed 的代码来说明这个问题。

my @list = 1..10;
my @results;
@results = @list[^24].hyper(:degree(2), :batch(1)).map({
    my $type = run('/bin/ls', :out).out.slurp.chars;
    $_ but role Mime { has $.mime = $type }
});

Rakudo 似乎试图与角色形成一个闭包,但却释放了存储在某个地方的数据。只有当线程使事情变慢时,这种情况才会明显。这是一种罕见的情况,语法是有效的,但语义是错误的。因此,Raku 的语法可以解析它,但编译器不能对这个匹配做任何有用的事情。在某种程度上,编译器能够处理这种情况而不发生崩溃,这是很高的评价。但是,如果能有一个警告就更好了。正如 jnthn指出的,这不是使用角色的正确方式。

因为有一个正确的方法来处理这种情况。我们需要定义一个带有参数的角色,作为我们属性的默认值。

sub get-filetype(IO() $_){ run('/usr/bin/file', '-b', '-i', .basename, :out).out.slurp }
role Mime[$type] { has $.mime = $type }
@results = @list[^24].hyper(:degree(2), :batch(1)).map({
    my $type = run('/bin/ls', :out).out.slurp.chars;
    $_ but Mime[$type]
});

我没能使用匿名参数角色。我们可以定义一个,把它存储在标量中,但不能实例化它。在标量上使用下标 [](以及许多其他东西)会告诉语法,假设我们要使用 Positional。

my $R = role :: [$t] {};
dd $R;
dd $R[42];
# OUTOUT: <anon|10> $R = <anon|10>
#         Could not instantiate role '<anon|10>':
#         Too few positionals passed; expected 2 arguments but got 1

有一种方法可以使用 MOP 来实现。我确实在 Metamodel::ParametricRoleHOW 中找到了正确的方法,但没能搞清楚如何使用。如果你确实知道如何使用 .^parameterize 请提供一个代码片段)。

并非真正的闭包形成角色,似乎是语法可以处理,但编译器不能处理的情况。这就留下了一个问题,那就是如何记录一个不应该存在的东西。这是一个陷阱,我们有一个章节来处理这些问题。但是这个放在离角色描述很远的地方。前两个 pull 请求已经写好了,接下来还需要写更多。

我很高兴文档是用支持超链接的语言写的。如果用书这种线性的东西来描述 Raku 这个网络,那是相当困难的。

by gfldex

comments powered by Disqus