将Seq(Seq)分配给数组

Val*_*kas 11 raku

将Seq(Seq)分配给多个类型数组而不先将Seq分配给标量的正确语法是什么?Seq是否会以某种方式展平?这将失败:

class A { has Int $.r }

my A (@ra1, @ra2);

#create two arrays with 5 random numbers below a certain limit

#Fails: Type check failed in assignment to @ra1; expected A but got Seq($((A.new(r => 3), A.n...)
(@ra1, @ra2) =
   <10 20>.map( -> $up_limit {
        (^5).map({A.new( r => (^$up_limit).pick ) })
    });
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 12

TL; DR绑定比分配更快,因此也许这是针对您问题的最佳实践解决方案:

:(@ra1, @ra2) := <10 20>.map(...);
Run Code Online (Sandbox Code Playgroud)

分配/复制

简化,您的无效代码是:

(@listvar1, @listvar2) = list1, list2;
Run Code Online (Sandbox Code Playgroud)

在P6中缀=方式分配/从复制的权值列表中= 一个或多个的容器上的变量离开的=

如果左侧的变量绑定到Scalar容器,则它将接受一项。然后,复制过程开始针对下一个容器变量。

如果左侧的变量绑定到Array容器,则它将接受所有剩余值。因此,您的第一个数组变量同时接收list1list2。这不是您想要的。

简化,这是克里斯托夫的答案:

@listvar1, @listvar2 Z= list1, list2;
Run Code Online (Sandbox Code Playgroud)

=静置片刻,Z是中缀版本zip程序。就像(一个物理zip在其左右两侧将连续的参数配对。当与运算符一起使用时,会将该运算符应用于该对。因此,您可以将上面的内容读取Z=为:

@listvar1 = list1;
@listvar2 = list2;
Run Code Online (Sandbox Code Playgroud)

任务完成。

但是分配 Array容器中需要:

  • 分别尽可能多的单个列表项复制容器中。(在示例代码中list1list2每个代码包含5个元素,因此总共有10个复制操作。)

  • 强迫容器根据需要调整大小以容纳物品。

  • 将项目使用的内存加倍(原始列表元素以及复制到Array元素中的重复项)。

  • 检查每个项目的类型是否匹配元素类型约束。

通常,分配比绑定要慢得多,而且占用的内存更多。

捆绑

:(@listvar1, @listvar2) := list1, list2;
Run Code Online (Sandbox Code Playgroud)

:=运营商的绑定在其右侧参数无论是在它的左边。

如果左侧只有一个变量,那么事情就特别简单。绑定后,变量现在精确地指向右边的内容。(这是特别简单和快速的—快速的类型检查就完成了。)

但这不是我们的情况。

绑定在其左侧也接受独立的签名文字。将:(...)在我的答案是一个独立的Signature文字。

(签名通常附加到不带冒号前缀的例程。例如,sub foo (@var1, @var2) {}(@var1, @var2)部分是附加到例程的签名foo。但是如您所见,一个人可以单独编写一个签名,并在P6前面加上一对来让它知道它是一个签名。主要区别在于签名中列出的所有变量都必须已经声明。)

当左侧有签名文字时,绑定将根据与接收例程签名的例程调用中的绑定参数相同的逻辑进行。(实际上,它在编译器中执行相同的代码路径。)

因此,最终结果是变量获得了它们在此子对象中拥有的值:

sub foo (@listvar1, @listvar2) { }
foo list1, list2;
Run Code Online (Sandbox Code Playgroud)

也就是说效果与以下相同:

@listvar1 := list1;
@listvar2 := list2;
Run Code Online (Sandbox Code Playgroud)

再次,就像克里斯托夫的答案一样,工作完成了。

但是这次,我们将避免上一节末尾描述的大部分分配开销。

  • “ my”让解析器知道您正在声明某些内容。'A'可能是一种类型,因此解析器允许这样做并且可以解决问题。接下来,它看到一个左括号,因此认为“啊,必须是要声明的标识符列表”。果然,当它到达右边的锅架时,它决定“是”,那是我的签名(...)。但是,当您改写以左括号开头但没有前面的“ my”开头的代码时,解析器会认为“我们在这里有一个*表达式”。到最后,paren解析为一个“ List”。而且,当它碰到`:=`时,现在为时已晚。 (2认同)
  • 我们很可能*可以*将其设置为DWIM,这样一来,如果`:=`发现左侧有一个列表,会将其转换为签名,或者想出另一种绑定方法,专门用于绑定到列表,但现在该语言只是抱怨,基本上是说“如果要像调用例程时那样绑定,请在冒号前面加一个冒号”。奇怪的是,我的(...)样式签名的行为与`:(...)`样式签名的行为完全不同(这与`sub foo(...)'样式完全不同。样式签名)。我真的不认为我们想要另一个... (2认同)

Chr*_*oph 11

不能完全确定是否是设计使然,但似乎发生的是两个序列都存储在中@ra1,而@ra2仍然为空。这违反了类型约束。

起作用的是

@ra1, @ra2 Z= <10 20>.map(...);
Run Code Online (Sandbox Code Playgroud)