非标量变量的解构赋值:绑定与赋值行为差异及疑问
Raku绑定与赋值解构的差异问题
绑定行为符合预期,但赋值行为却不符合:
my ($a, @b, $c) := (42, <a b c>, 42); say [$a, @b, $c]; # OUTPUTS: [42 (a b c) 42] my ($d, @e, $f) = (42, <a b c>, 42); say [$d, @e, $f]; # OUTPUTS: [42 [(a b c) 42] (Any)]
我假设带有@(或%)符号的变量会捕获所有剩余值。
现提出以下技术问题:
- 我的上述假设是否正确,或是该机制另有运作逻辑?
- 能否在赋值操作中实现与绑定操作类似的解构行为?
问题1解答
你的假设不正确,绑定(:=)和赋值(=)的解构逻辑完全不同:
- 绑定操作:变量直接关联到右侧对应位置的原有值,不复制数据。
($a, @b, $c) := ...中每个变量分别绑定到右侧列表的三个元素,@b绑定到第二个元素(<a b c>列表),因此结果符合预期。 - 赋值操作:将右侧数据复制到左侧变量,遵循扁平化解构规则:左侧的数组变量
@e会吸收右侧当前位置开始的所有剩余元素。示例中$d取第一个元素42后,剩下的<a b c>和42都被@e吸收,导致@e变为[(a b c) 42],$f无值可取则默认是Any。
问题2解答
可以通过两种方式在赋值时实现类似绑定的解构行为:
- 用括号包裹数组变量:让数组变量仅接收右侧对应位置的单个元素,而非剩余所有值:
my ($d, (@e), $f) = (42, <a b c>, 42); say [$d, @e, $f]; # OUTPUTS: [42 (a b c) 42]
这里(@e)表示仅取右侧第二个元素<a b c>赋值给@e,后续的42留给$f。
- 使用逐项赋值:明确指定每个变量对应的右侧元素:
my ($d, @e, $f) = (42 => $d, <a b c> => @e, 42 => $f); say [$d, @e, $f]; # OUTPUTS: [42 (a b c) 42]
这种方式直接一一对应赋值,避免数组变量吸收剩余元素的行为。
内容的提问来源于stack exchange,提问作者fingolfin
相关产品推荐
相关产品推荐

