【问题标题】:Perl6; multi subPerl6;多子
【发布时间】:2018-05-09 18:53:01
【问题描述】:

对于下面的多子脚本:

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 新手

【问题讨论】:

    标签: signature raku


    【解决方案1】:

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

    $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() 接受任何将强制转换为 Str 的内容。

    【讨论】:

    • 当然你可以全力以赴:``` sub Screen_get_valid_string( Str() $prompt, Int :$max_length = 999, Bool :$accept_empty_string = False ) ```
    【解决方案2】:

    主要问题是在 Perl 6 中 Bool like True 实际上是 Int like 999 的类型所以即使你在签名中声明它们的类型(Bool $accept_empty_stringInt $max_length) ,将很难将它们分开。所以在这种情况下,Perl 6 很难将它们分开。

    但如果你限制值,你仍然可以使用定位

    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 有助于限制变量可能取的值,这有助于消除 multi 的选择。

    【讨论】:

    • 请注意,where $_ == True|False 可能只是 where True|False
    • "主要问题是在 Perl 6 中,BoolTrue 实际上是 Int 的类型,像 999。"这根本不相关。有两个签名。两者都没有指定任何类型信息。一个接受 2 或 3 个位置参数。另一个指定 1 或 2。呼叫有 2。那么选择哪个?这是完全模棱两可的。那就是问题所在。通过添加一些类型信息,您可以使该参数的类型信息更窄。所以它得到了第一个dib。如果匹配,则获胜。否则,对方会赢。它匹配,所以它赢了。
    • @raiph,在这种情况下,我不敢苟同。我尝试使用类型信息,它有完全相同的问题。我应该指定我试过了,也......
    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 2019-07-09
    相关资源
    最近更新 更多