raku - 打电话而不调用其他候选人? "other candidates"是什么?其他候选人名单是否已经耗尽?该列表可用吗?

标签 raku dispatch

我正在尝试发送地址 this issue ,实际上是由 this other stackoverflow question 提出的与callwith的不同行为有关和 samewith 。后者似乎定义得很清楚,但是用 callwith 就不太清楚了。

看看这个例子:

proto how-many(|) {*}

multi sub how-many( Pair $a, Pair $b ) {
    say "Int $a and $b";
    return "There are $a and $b"

}
multi sub how-many( $a, $b ) {
    say "Not int $a and $b";
    my $calling = callwith( 1 => $a, 2 => $b );
    return $calling;
}

say how-many( "little piggie","littler piggie" );

根据文档,callwith 应该调用下一个匹配的候选者。但是,这是输出:

Not int little piggie and littler piggie
(Any)

所以它调用了 how-many 的第二个版本,然后调用一个不存在的函数(显然)并返回 Nil,它作为 Any 传递 到调用例程。

我也尝试过使用不同的签名,但这也不起作用。文档中的示例显然表明只有当变量属于同一类层次结构时它才有效。是这样吗?可能不是,因为将位置签名更改为 Any $a, Any $b 也不起作用,也无法更改声明的顺序。

Above, changing callwith with samewith will obviously work, but I'm trying to understand how callwith works, not make the code above work.

此外,它似乎是在类层次结构中向下,而不是向上。这个example in roast ,Perl 6 测试套件,有效:

my $tracker = '';
multi d($x)     { $tracker ~= 'Any' ~ $x };
multi d(Int $x) { $tracker ~= 'Int'; callwith($x+1); $tracker ~= 'Int' };
lives-ok { d(3) }, 'can call callwith inside a multi sub';

但是,如果我们更改它,以便我们从层次结构的底部使用 callwith,如下所示:

my $tracker = '';
multi d($x)      { $tracker ~= 'Any' ~ callwith( "called-with" => $x) };
multi d(Pair $x) { $tracker ~= "Pair $x" };

say d( 3 );

失败了

Use of Nil in string context in sub d at rewrite-test-callwith.p6 line 6

这是预期的行为吗?

最佳答案

所有 callwithnextwithcallsamenextsame 遍历候选集合由原始参数确定。因此,虽然 callwith 可以用来替换参数,但这就是它所做的一切。它不会导致要迭代的预定候选列表发生变化。

考虑这三个候选人:

multi foo(Any $x)  { say "In Any case with $x" }
multi foo(Real $x) { say "In Real case with $x"; callwith($x.Int); }
multi foo(Int $x)  { say "In Int case with $x"; callsame(); }

我们可以使用 .cando 询问哪些候选人申请,并向其传递 Capture。因此:

.say for &foo.cando(\(42));

将产生以下输出:

sub foo (Int $x) { #`(Sub|78402328) ... }
sub foo (Real $x) { #`(Sub|78412816) ... }
sub foo ($x) { #`(Sub|78412968) ... }

由于 3 名候选人全部匹配。调用 foo(42) 将产生以下输出:

In Int case with 42
In Real case with 42
In Any case with 42

相比之下,:

.say for &foo.cando(\(4.2));

输出为:

sub foo (Real $x) { #`(Sub|78412816) ... }
sub foo ($x) { #`(Sub|78412968) ... }

调用 foo(4.2) 会使 callwith 迭代这些候选者:

In Real case with 4.2
In Any case with 4

在最一般的候选中,callwith 或类似的方法不会产生任何效果,并且计算结果为 Nil

虽然这里的示例是多重子函数,但这同样适用于包装器和非多重方法,它们也遍历预定的列表。

最后,还值得观察的是,如果每次都有新的调度,我给出的示例最终将成为无限递归。通过遍历预先确定的候选列表,这种情况永远不会发生。

请注意,这些都不适用于 samewith,它的存​​在正是为了进行全新的调度。

关于raku - 打电话而不调用其他候选人? "other candidates"是什么?其他候选人名单是否已经耗尽?该列表可用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51239934/

相关文章:

regex - 无法在 perl6 中编写语法来解析带有特殊字符的行

raku - Raku 在编译时执行哪些类型检查?将来可能会改变吗?

windows - Raku:带空格的 shell 调用的语法是什么?

raku - 文件 ctime 在 perl 5 和 perl 6 下不同

search - Perl 6中多于一根针的索引

ios - _dispatch_call_block_and_release 崩溃

java - 多态性 - 简单

ios - 如何正确多线程? UIAlertView不显示,只灰屏

具有自定义初始化的 C++ 静态分派(dispatch)

windows - 了解 Windows 的系统调用调度程序?