8

For the following multi sub script:

multi sub Screen_get_valid_string($prompt, $accept_empty_string, $max_length = 999) { return "abc" }
multi sub Screen_get_valid_string($prompt, $max_length = 999)                       { return "def" }

my $return = Screen_get_valid_string("enter value for string => ", True);

say 'return  is ', $return;

I receive the following error:

Ambiguous call to 'Screen_get_valid_string';
these signatures all match:
:($prompt, $accept_empty_string, $max_length = 999)
:($prompt, $max_length = 999)

The only way I found to have the right multi sub called was to use named parameters:

multi sub Screen_get_valid_string(:$prompt, :$accept_empty_string, :$max_length = 999) { return "abc" }
multi sub Screen_get_valid_string(:$prompt, :$max_length = 999)                        { return "def" }


my $return = Screen_get_valid_string(prompt => "enter value for string => ", accept_empty_string => True);

say 'return  is ', $return;

The result is :

return  is abc

Thank you

p.s. worked in Perl5; new to Perl6

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

2 Answers2

6

The error you are getting is because you have the default value set. As such the parser doesn't know if you're asking for

$prompt = "enter value for string => "
$accept_empty_string = True
$max_length = 999

Or

$prompt = "enter value for string => "
$max_length = True

With no type hints there's no was to tell from just the positional which of the two options is correct. Adding types would help (as suggested by JJ Merelo). You can also mix and match positional and named arguments which may help in this situation :

sub Screen_get_valid_string( $prompt, 
                             :$max_length = 999, 
                             :$accept_empty_string = False ) 

In this situation you don't need a multi. $prompt is always required and the other two are flags with default values.

I gave a talk covering the various options for signatures at LPM recently it might be helpful.

https://www.youtube.com/watch?v=obYlOurt-44

Of course you can go the whole hog with :

sub Screen_get_valid_string( Str() $prompt, 
                             Int :$max_length = 999, 
                             Bool :$accept_empty_string = False ) 

Note the Str() accepts anything that will coerce to a Str.

Scimon Proctor
  • 4,558
  • 23
  • 22
  • Of course you can go the whole hog with : ``` sub Screen_get_valid_string( Str() $prompt, Int :$max_length = 999, Bool :$accept_empty_string = False ) ``` – Scimon Proctor May 11 '18 at 08:15
3

The main problem is that in Perl 6 a Bool like True is actually a type of Int like 999 so even if you declare their type (Bool $accept_empty_string, Int $max_length) in the signature, it is going to be difficult to make them apart. So in this case, Perl 6 has a hard time making them apart.

But you can still use Positionals if you restrict values

multi sub Screen_get_valid_string($prompt, 
                                  $accept_empty_string where True|False, 
                                  $max_length = 999) { 
    return "abc" 
}
multi sub Screen_get_valid_string($prompt, $max_length = 999) { 
   return "def" 
}

my $return = Screen_get_valid_string("enter value for string => ", True);

say 'return  is ', $return; # writes "return is  abc"

where helps constrain the possible values the variable might take, which helps disambiguate the choice of multi.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
  • 4
    Note that `where $_ == True|False` could be simply `where True|False` – Jonathan Worthington May 09 '18 at 19:15
  • 1
    "The main problem is that in Perl 6 a `Bool` like `True` is actually a type of `Int` like `999`." That's not at all relevant. There are two signatures. Neither specifies any type info. One accepts either 2 or 3 positional arguments. The other specifies either 1 or 2. The call has 2. So which to pick? It's entirely ambiguous. That's the problem. By adding some type info you made the one with the type info narrower for that parameter. So it gets first dibs. If it matches, it wins. If it doesn't, the other would win. It matches so it wins. – raiph May 09 '18 at 22:26
  • 1
    @raiph, in this case, I beg to differ. I tried with type info, and it had exactly the same problem. I should specify I tried that, also... – jjmerelo May 10 '18 at 05:28