TL;DR 绑定比赋值更快,所以也许这是解决您问题的最佳实践解决方案:
:(@ra1, @ra2) := <10 20>.map(...);
虽然比已接受答案中的解决方案更丑陋,但这在算法上更快,因为绑定是O(1),而在被绑定列表的长度中分配的O(N)。
分配/复制
简化,您的非工作代码是:
(@listvar1, @listvar2) = list1, list2;
在 Raku 中缀= 表示从= 右侧的赋值/复制到= 左侧的一个或多个container 变量。
如果左边的变量绑定到Scalar container,那么它将分配右边的值之一。然后赋值过程从左边的下一个容器变量和右边的下一个值开始。
如果左侧的变量绑定到Array container,则它将用完右侧的所有剩余值。所以你的 first 数组变量同时接收到list1 和list2。这不是你想要的。
简单来说,这是 Christoph 的回答:
@listvar1, @listvar2 Z= list1, list2;
暂时搁置=,Z 是the zip routine 的中缀版本。就像 (a physical zip 将连续参数在其左右配对。当与运算符一起使用时,它将该运算符应用于该对。因此您可以将上面的Z= 阅读为:
@listvar1 = list1;
@listvar2 = list2;
工作完成了吗?
分配到 Array 容器需要:
分配通常比绑定要慢得多,而且占用更多内存...
绑定
:(@listvar1, @listvar2) := list1, list2;
:= 运算符 binds 左边的参数到右边的参数。
如果左边有一个变量,那么事情就特别简单。绑定后,变量现在精确地引用右边的内容。 (这特别简单和快速——快速类型检查就完成了。)
但我们的情况并非如此。
Binding 还接受其左侧的独立签名文字。我的答案中的 :(...) 是独立的 Signature 文字。
(签名通常附加到不带冒号前缀的例程中。例如,在sub foo (@var1, @var2) {} 中,(@var1, @var2) 部分是附加到例程foo 的签名。但正如您所看到的,可以编写签名分开,并通过在一对括号前面加上冒号来让 Raku 知道它是一个签名。一个关键的区别是签名中列出的任何变量都必须已经声明。)
当左边有一个签名文字时,绑定会根据与在例程调用中绑定参数相同的逻辑发生在接收例程的签名中。
所以最终结果是变量获得了它们在这个 sub 中的值:
sub foo (@listvar1, @listvar2) { }
foo list1, list2;
也就是说效果是一样的:
@listvar1 := list1;
@listvar2 := list2;
再一次,就像克里斯托夫的回答一样,工作完成了。
但是这样我们就可以避免分配开销。