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;

Is this error message wrong?

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

The error message says index() will accept a third parameter of 'Any', which is what it was given when I verify with $foo.WHAT.

raiph
  • 31,607
  • 3
  • 62
  • 111
Clint
  • 109
  • 2

3 Answers3

3

The third parameter of index is defined as an Int that is actually coerced to Cool (Cool being a class that can represent either a number or a string in Perl 6). But the way you have defined it my $foo (whose type will be "Any") it can't be recognized as any of them. As soon as you give it a value, either "0" or 0, that will work.

my $foo = 0;  

since the type will be recognized correctly by index's signature.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
2

So, just to clarify, the error is saying

caller [of subroutine] index [passing params of type] (Str: Str, Any)

cannot be resolved [because it does not match any of] The available index() definitions:

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, *%_)

==========

imho, this error wording will be harder to understand esp. for newbies where it occurs on built-in subroutines due to the thorough use of signature tools such as high order types (e.g. Cool), smilies, $:(whatever that is) and parser internal names such as $needle

maybe could do some magic such as “likely 3rd param caused error as defns require it to be Int:D or Cool:D”

librasteve
  • 6,832
  • 8
  • 30
  • I like where you're headed with your rewording of the error. I'm wondering why the original error / your improvement says "caller" rather than "call". It's not "passing params of type" but rather "passing args of type". I'm also thinking we could say "can not be *dispatched* because it does not match any of the *candidates*:". – raiph May 06 '18 at 21:22
1

I discuss how we might improve the error message in the second half of this answer. But first:

Is this error message wrong?

Well, you've misunderstood it, so it's wrong in that sense.

The error message says index() will accept

To be more precise, the message begins:

Cannot resolve caller 

which refers to the index() call, i.e. not "what index() will accept" but rather what the code actually asked for which was:

index $word, "a", $foo;

a third parameter of Any, which is what it was given when I verify with $foo.WHAT.

Yes, Any is the type of the third value of "what it was given", but that refers to the value of the third argument of a call to index(), not the third parameter of an index() definition.

The available index() definitions are:

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, *%_)

None of these four definitions, which have distinct signatures, include a third parameter that will accept the given corresponding third argument in the call, as stored in the call's capture.

Ideas about how to improve the error message

Perl 6 culture includes an "awesome error messages" focus, and arguably related confusion has come up before (eg the exchange that led to this comment I made on an earlier SO).

So let's dissect this a little bit further so we can see if we come up with any good ideas for clearly improving the message, or some doc, or whatever.

I think your misunderstanding was rooted in lack of clarity about the distinction between arguments (and calls/captures) and parameters (and definitions/signatures), and particularly your interpretation of this bit of the error message:

index(Str: Str, Any)

The bit after index looks just like a signature, i.e. it looks like a list of, well, thingies (let's call it the types of "pargs") that would be acceptable to an index() definition if used in an index() call.

But it's not a signature, part of an index() definition. Instead it's actually a list of types corresponding to the list of arguments in an index() call.

I think this capture analysis and display is specifically constructed to make it easier for the reader of the error message to figure out what went wrong in the attempt to bind the capture to a matching signature.

Unfortunately, while it may now serve that purpose for you if you've understood this answer, we're still left with the problem that your initial interpretation led you to think the error message was just plain wrong -- and others may make the same mistake.

Anyhow, I think that's enough discussion in my answer. If you wish to pursue this please add comments to this answer and/or your question. Does what I've written so far make sense to you? Got any ideas?

Community
  • 1
  • 1
raiph
  • 31,607
  • 3
  • 62
  • 111
  • Thank you so much for the detailed and gentle response. The two resources I've primarily use to learn Perl6 is "Think Perl6" and perl6intro.com. Neither of these went into detail of anything found in the definition section of index(). So from my perspective, it looks as if this error message is not very beginner-friendly. But I will admit, that I just misread index(Str: Str, Any). At the time it looked like three parameters, which would have matched what I was doing. the lack of a second comma should have tipped me off. Example, index(Str, Str, Any). – Clint May 06 '18 at 20:12
  • You're welcome. Sub (non method) signatures won't have a `:`, so no tipoff. I think there are two primary problems: 1) most languages don't do multiple dispatch, so a call either works or it doesn't, and there's no notion of a call that needs to be resolved against a list of candidates, so multiple dispatch introduces an extra learning curve; and 2) the error message, in its zeal to make it easy once you've dealt with problem 1, makes call/capture/argument data look similar to definition/signature/parameter data and that's going to confuse someone who has *not* yet fully dealt with problem 1. – raiph May 06 '18 at 21:13
  • @Clint Please see p6steve's answer and my comment. – raiph May 06 '18 at 21:24