在超级方法链中使用带有收集/接收的 CALL-ME 不起作用

pmq*_*mqs 7 raku

一直在玩方法链和CALL-ME

下面是我用来玩的一个玩具类。它CALL-ME只是调用double给定值的 Seq 方法。

class Math does Callable
{
    method  CALL-ME(Iterable:D $i)
    {
        gather {
            $i.map: -> $v { take self.double($v) } ;
        }
    }

    method double($x) { return $x * 2}
}

my $d = Math.new();
Run Code Online (Sandbox Code Playgroud)

首先检查是否可以将Math对象包含$d在方法链中。

这段代码

(1,2,3).map( * + 1 ).$d.map( * +1).say;
Run Code Online (Sandbox Code Playgroud)

输出正确的结果

(5 7 9)
Run Code Online (Sandbox Code Playgroud)

现在放入hyper方法链中

(1,2,3).hyper.map( * + 1 ).$d.map( * + 1 ).say;
Run Code Online (Sandbox Code Playgroud)

这次的输出是

A worker in a parallel iteration (hyper or race) initiated here:
  in block <unit> at callme.raku line 6

Died at:
    take without gather
      in block  at callme.raku line 6
Run Code Online (Sandbox Code Playgroud)

其中第 6 行是该take行。

CALL-ME我可以通过将 替换为另一个调用(如下所示)来解决这个问题map,但这留下了一个问题:为什么map可以做正确的事情,但CALL-ME不能?

(1,2,3).hyper.map( * + 1 ).map( -> $v { $d.double($v) } ).map( * +1).say;
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

[编辑]更新以下来自罗利的回复。

假设我创建了一个更大的类,其中还包括一个CALL-ME. 理想情况下,我希望方法链接能够在串行和并发工作流程中以最佳方式运行,而用户不必跳过太多的障碍。

如果我将gather/take保留CALL-ME在串行上下文中时,我会得到延迟执行,但在hyper使用时它会完全中断。

或者,删除gather/take意味着我有一个CALL-ME可以在串行和超上下文中工作的。缺点是串行用例最终以急切模式运行。

有没有办法CALL-ME通过测试它运行的上下文来实现这两种方式?

is-hyper-active就像下面的假设一样

    method  CALL-ME(Iterable:D $i)
    {
        if is-hyper-active {
            $i.map: -> $v { take self.double($v)
        } else {
            gather {
                $i.map: -> $v { take self.double($v) } ;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Raw*_*ler 6

Hyper与传统的有很大不同Seq,使用gather并且take很可能由于 的异步性而无法工作Hyper。相反,您可以从您的中删除gatherand并简单地返回地图的结果以使其工作:takeCALL-ME

class Math does Callable {
    method CALL-ME(Iterable:D $i) {
        $i.map: -> $t { self.double($t) };
    }

    method double($x) { return $x * 2}
}
Run Code Online (Sandbox Code Playgroud)

现在你应该看到:

(1,2,3).hyper.map( * + 1 ).$d.map( * + 1 ).say;
Run Code Online (Sandbox Code Playgroud)

作品。

就我个人而言,我避免gather并且take更喜欢仅使用方法和函数来构造我Seq的。return另外,省略在多个地方不返回的 on 函数也更惯用。