cod*_*ons 10 destructuring variable-assignment flatten assignment-operator raku
我知道列表赋值会使其左侧变平:
\nmy ($a, $b, $c);\n($a, ($b, $c)) = (0, (1.0, 1.1), 2);\nsay "\\$a: $a"; # OUTPUT: \xc2\xab$a: 0\xc2\xbb\nsay "\\$b: $b"; # OUTPUT: \xc2\xab$b: 1 1.1\xc2\xbb <-- $b is *not* 1\nsay "\\$c: $c"; # OUTPUT: \xc2\xab$c: 2\xc2\xbb <-- $c is *not* 1.1\nRun Code Online (Sandbox Code Playgroud)\n我也明白我们可以用来:($a, ($b, $c)) := (0, (1.0, 1.1))获得非扁平化行为。
我不明白的是为什么在列表分配期间左侧被展平。这是两个问题:首先,这种扁平化行为如何与语言的其余部分相适应?其次,自动展平是否允许任何在左侧不展平时不可能出现的行为?
\n关于第一个问题,我知道 Raku 历史上有很多自动扁平化行为。在Great List Refactor之前,像这样的表达式my @a = 1, (2, 3), 4会自动展平其右侧,从而产生 Array [1, 2, 3, 4];同样,map许多其他迭代结构也会使他们的论点变得扁平化。不过,在 GLR 之后,Raku 基本上不会在未经告知的情况下将列表扁平化。事实上,我想不出任何其他情况下 Raku 会在没有flat、.flat、|、 或*@以某种方式参与的情况下扁平化。(@_创建隐式*@)。我是否遗漏了什么,或者列表分配中的 LHS 行为真的与后 GLR 语义不一致吗?这种行为是历史上的怪事,还是仍然有意义?
关于我的第二个问题,我怀疑列表分配的扁平化行为可能在某种程度上有助于支持懒惰。例如,我知道我们可以使用列表分配来使用惰性列表中的某些值,而无需生成/计算所有 \xe2\x80\x93 ,而使用:=列表则需要计算所有 RHS 值。但我不确定是否/如何自动展平 LHS 来支持这种行为。
=我还想知道自动展平是否与可以传递给元运算符 \xe2\x80\x93 的事实有关,与 不同的是:=,如果与元运算符一起使用,它会生成“太繁琐”的错误。但我不知道自动展平如何/是否可以减少=“繁琐”。
[编辑:我早在2015 年 5 月 2日就发现 IRC 提到了“(GLR 保留的)列表分配扁平化的决定” ,所以很明显这个决定是有意为之且良好的-有理有据。但到目前为止,我还没有找到这样的理由,并怀疑这可能是在面对面的会议上决定的。所以我希望有人知道。]
\n最后,我还想知道LHS 在概念层面上是如何扁平化的。(我并不是指具体的 Rakudo 实现;我的意思是作为一种心理模型)。以下是我对绑定与列表赋值的思考方式:
\nmy ($a, :$b) := (4, :a(2)); # Conceptually similar to calling .Capture on the RHS\nmy ($c, $d, $e);\n($c, ($d, $e) = (0, 1, 2); # Conceptually similar to calling flat on the LHS\nRun Code Online (Sandbox Code Playgroud)\n除了实际上在第 1 行中调用.CaptureRHS 有效之外,而flat在第 3 行中调用 LHS 会引发Cannot modify an immutable Seq错误 \xe2\x80\x93 ,考虑到我们Seq一直压平 s,我觉得这非常令人困惑。那么是否有更好的心理模型来思考这种自动扁平化行为呢?
预先感谢您的任何帮助。我正在尝试更好地理解这一点,作为改进相关文档工作的一部分,因此您可以提供的任何见解都将支持这项工作。
\n不知何故,以相反的顺序回答问题部分对我来说感觉更自然。:-)
其次,自动展平是否允许任何在左侧不展平时不可能出现的行为?
将列表的前几个(或前几个)项目分配给标量并将其余项目放入数组中是相对常见的。列表分配下降到左侧的可迭代是使此工作有效的原因:
my ($first, $second, @rest) = 1..5;
.say for $first, $second, @rest;'
Run Code Online (Sandbox Code Playgroud)
输出为:
1
2
[3 4 5]
Run Code Online (Sandbox Code Playgroud)
对于尊重结构的绑定,它会更像:
my ($first, $second, *@rest) := |(1..5);
Run Code Online (Sandbox Code Playgroud)
首先,这种扁平化行为如何与语言的其他部分相适应?
一般来说,结构没有意义的操作会将其扁平化。例如:
# Process arguments
my $proc = Proc::Async.new($program, @some-args, @some-others);
# Promise combinators
await Promise.anyof(@downloads, @uploads);
# File names
unlink @temps, @previous-output;
# Hash construction
my @a = x => 1, y => 2;
my @b = z => 3;
dd hash @a, @b; # {:x(1), :y(2), :z(3)}
Run Code Online (Sandbox Code Playgroud)
当然,列表分配也可以以尊重结构的方式定义。这些事情的发生往往有多种原因,但一方面,当你确实想做结构化的事情时,语言已经有了绑定;另一方面,这种情况my ($first, @rest) = @all太常见了,以至于无法将想要它的人送入绑定/模糊的强大工具路径。