Perl6; multi sub

8

对于下面的多个下标脚本:

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;

我收到了以下错误信息:

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

我发现调用正确的多子程序的唯一方法是使用命名参数:
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;

结果是:
return  is abc

谢谢。

顺便提一下,我之前在Perl5中有工作经验,现在开始接触Perl6。

2个回答

6
您遇到的错误是由于您设置了默认值。因此,解析器不知道您是否要求


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

或者

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

如果没有类型提示,仅通过位置无法确定两个选项中的哪一个是正确的。添加类型会有所帮助(正如JJ Merelo建议的那样)。您还可以混合使用位置参数和命名参数,在这种情况下可能会有所帮助:

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

在这种情况下,您不需要使用 multi。$prompt 始终是必需的,而另外两个是带有默认值的标志。
我最近在 LPM 上做了一个关于签名各种选项的演讲,可能会有所帮助。
当然,您可以使用以下完整选项: https://www.youtube.com/watch?v=obYlOurt-44
sub Screen_get_valid_string( Str() $prompt, 
                             Int :$max_length = 999, 
                             Bool :$accept_empty_string = False ) 

请注意,Str()接受任何可以强制转换为字符串的内容。

当然,你可以使用以下完整的代码:sub Screen_get_valid_string( Str() $prompt, Int :$max_length = 999, Bool :$accept_empty_string = False ) - Scimon Proctor

3
主要问题在于Perl 6中,像True这样的Bool实际上是Int类型的一种,就像999一样,因此即使在签名中声明它们的类型(Bool $accept_empty_string,Int $max_length),也很难区分它们。所以在这种情况下,Perl 6很难区分它们。
但是,如果限制值,仍然可以使用Positionals。
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 关键字可以限制变量可能的取值范围,有助于消除多个选择的歧义。


4
请注意,where $_ == True|False 可以简写为 where True|False - Jonathan Worthington
1
主要问题是在Perl 6中,像True这样的Bool实际上是像999这样的Int类型。这完全不相关。有两个签名,都没有指定任何类型信息。一个接受2或3个位置参数。另一个指定1或2个。调用有2个。那么该选择哪个?这完全是模棱两可的。这就是问题所在。通过添加一些类型信息,您使具有类型信息的参数更窄。因此它首先获得机会。如果匹配,则获胜。如果不匹配,则另一个将获胜。它匹配,所以它获胜。 - raiph
1
@raiph,在这种情况下,我不太同意。我尝试使用type info,但遇到了完全相同的问题。我应该说明一下,我也试过那个... - jjmerelo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接