6
sub count-a {
    my $word = "banana";
    my $count = 0;
    my $foo;      #  Source of error: $foo intentionally not given a value.
                 #  The value ought to be zero.

    while True {
      $foo = index $word, "a", $foo;
      last unless $foo.defined;
      $foo++;
      $count++
  }
  return $count;
}

say count-a;

这个错误信息是错误的吗?

Cannot resolve caller index(Str: Str, Any); none of these signatures match:
  (Str:D $: Cool:D $needle, *%_)
  (Str:D $: Str:D $needle, *%_)
  (Str:D $: Cool:D $needle, Cool:D $pos, *%_)
  (Str:D $: Str:D $needle, Int:D $pos, *%_)
in sub count-a at scrap.p6 line 11
in block <unit> at scrap.p6 line 18

错误消息说 index() 将接受“Any”的第三个参数,这是我用 $foo.WHAT 验证时给出的。

4

3 回答 3

3

of的第三个参数index被定义为一个 Int,它实际上被强制转换为Cool在 Perl 6 中可以表示数字或字符串的类Cool)。但是您定义它的方式(其类型将是“任何”)它不能被识别为其中任何一个。只要你给它一个值,要么 要么,这将起作用。my $foo"0"0

my $foo = 0;  

因为类型将被index的签名正确识别。

于 2018-05-04T16:54:20.190 回答
2

所以,只是为了澄清,错误是说

调用者[子程序]索引[传递类型的参数] (Str: Str, Any)

无法解决[因为它不匹配任何]可用的 index() 定义:

index(Str:D $: Cool:D $needle, *%_)
index(Str:D $: Str:D $needle, *%_)
index(Str:D $: Cool:D $needle, Cool:D $pos, *%_)
index(Str:D $: Str:D $needle, Int:D $pos, *%_)

==========

恕我直言,这个错误措辞将更难理解,尤其是。对于由于彻底使用诸如高阶类型(例如 Cool)、表情符号、$:(无论是什么)和解析器内部名称(例如 $needle)等签名工具而出现在内置子例程上的新手

也许可以做一些魔术,例如“可能第三个参数导致错误,因为定义要求它是 Int:D 或 Cool:D”</p>

于 2018-05-06T17:11:48.293 回答
1

我在这个答案的后半部分讨论了我们如何改进错误消息。但首先:

这个错误信息是错误的吗?

好吧,你误解了它,所以在这个意义上它是错误的。

错误消息说index()将接受

更准确地说,消息开始于:

Cannot resolve caller 

它指的是index() call,即不是“index()将接受什么”,而是代码实际要求的内容是:

index $word, "a", $foo;

的第三个参数Any,这是我验证时给出的$foo.WHAT

是的,Any是“给定什么”的第三个的类型,但它指的是调用的第三个参数的值,而不是定义的第三个参数的值。index()index()

可用的index()定义是:

index(Str:D $: Cool:D $needle, *%_)
index(Str:D $: Str:D $needle, *%_)
index(Str:D $: Cool:D $needle, Cool:D $pos, *%_)
index(Str:D $: Str:D $needle, Int:D $pos, *%_)

这四个具有不同签名的定义中没有一个包含第三个参数,该参数将接受调用中给定的对应第三个参数,如存储在调用的捕获

关于如何改进错误消息的想法

Perl 6 文化包括一个“令人敬畏的错误消息”焦点,并且可以说相关的混淆以前出现过(例如,导致我在较早的 SO 上发表此评论的交流)。

因此,让我们进一步剖析一下,看看我们是否想出了任何好的想法来明确改进信息,或者一些文档,或者其他什么。

我认为您的误解源于对参数(和调用/捕获)和参数(和定义/签名)之间的区别缺乏明确性,特别是您对这部分错误消息的解释:

index(Str: Str, Any)

后面的位index 看起来就像一个签名,即它看起来index()像一个列表,好吧,如果在调用中使用,定义可以接受的东西(我们称之为“pargs”的类型)index()

但这不是签名,而是index()定义的一部分。相反,它实际上是与调用中的参数列表相对应的类型列表index()

我认为这种捕获分析和显示是专门构建的,以使错误消息的读者更容易找出在尝试将捕获绑定到匹配签名时出了什么问题。

不幸的是,虽然如果您已经理解了这个答案,它现在可能会为您服务,但我们仍然存在一个问题,即您最初的解释导致您认为错误消息完全是错误的——其他人可能也会这样做错误。

无论如何,我认为我的回答已经足够讨论了。如果您希望继续这样做,请在此答案和/或您的问题中添加评论。到目前为止我写的内容对你有意义吗?有什么想法吗?

于 2018-05-04T21:02:26.287 回答