6

I've created a class which contains multi definitions for function overloading, however when I try to call the class and the overloaded method, it throws an error. A working example which can be run to produce this error is shown below:

class Test
{
    multi test(@data) {
        return test(@data, @data.elems);
    }

    multi test(@data, $length) {
        return 0;
    }
}

my @t = 't1', 't2', 't3';
say Test.test(@t);

Error:

No such method 'test' for invocant of type 'Test'. Did you mean any of these?
    List
    Set
    gist
    list

  in block <unit> at test.p6 line 13

I may be doing this wrong, can someone point me to the correct way to do this?

Edit: I'm effectively trying to make this a module, which I can use for other things.

ikegami
  • 367,544
  • 15
  • 269
  • 518
madcrazydrumma
  • 1,847
  • 3
  • 20
  • 38
  • 2
    See [The visual map for `Routine` relationships](https://docs.perl6.org/type/Routine#Type_Graph). `multi` can be applied to definition of a `macro`, `sub`, `method`, `regex`, `rule`, `token`, or `submethod`. If you don't say which it defaults to `sub`. – raiph Jul 12 '18 at 10:11

3 Answers3

8

You need add the self keyword before your test method:

class Test
{

    multi method test(@data) {
        return self.test(@data, @data.elems);
    }

    multi method test(@data, $length) {
        return 0;
    }

}

my @t = 't1', 't2', 't3';
say Test.test(@t);

note: In Perl 6 class, use method keyword to declare a method.

chenyf
  • 5,048
  • 1
  • 12
  • 35
  • 1
    Your answer reads a bit oddly (at least to me) given that the error message in @madcrazydrumma's question is due to not using the`method` keyword, per your note at the end of your answer, rather than not using `self.`, per your opening explanation. Your answer is correct, and the OP has accepted it, as would I, so I'm just leaving this comment because I imagine it might be helpful to future readers. – raiph Jul 12 '18 at 09:08
7

The reason you're getting the no such method error is that multi defaults to sub unless told other wise. You need multi method test

Scimon Proctor
  • 4,558
  • 23
  • 22
2

Other answers have to helped explain the usage for multi method but optional parameters might be a simpler way to get the same result:

#!/usr/bin/env perl6
use v6;

class Test
{
    method test(@data, Int $length = @data.elems) {
        say 'In method test length ', $length, ' data ', @data.perl;
        return 0;
    }
}

my @t = 't1', 't2', 't3';
say Test.test(@t);
mr_ron
  • 471
  • 3
  • 8