deepmap 创建的数组中的不可变(非容器化)元素
Immutable (uncontainerized) elements in arrays created by deepmap
如果我正确理解 Raku 文档,数组的元素总是容器化的,即标量。但是,deepmap 方法似乎创建了(内部)具有未容器化元素的数组:
my @a = [1, [2, 3]];
my @b = @a.deepmap: *.clone;
say @b[0].VAR.^name; # Scalar, this is OK
say @b[1].^name; # Array, as expected
say @b[1][0].VAR.^name; # Int, why?
@b[0] = 4; # this works
@b[1][0] = 5; # error: Cannot assign to an immutable value
为什么会这样?
对于上下文,我最初想使用 .deepmap: *.clone
创建一个深拷贝,但我需要该拷贝是可变的。我使用 @a.deepmap: { my $ = .clone }
解决了这个问题,但我仍然很好奇为什么会这样。
If I understand the Raku docs correctly, the elements of Arrays are always containerized, i.e. Scalars.
几乎正确,但不完全正确 – 数组初始化(即使用 [1, 2]
)将值容器化,但这并不意味着元素总是容器化.例如,您可以 explicitly bind a value 到数组中的某个位置。
或者,正如您所发现的,当以不寻常的方式创建数组时,您可能会得到一个非容器化的值。让我们看看 deepmap
在这里做了什么:
my @a = [1, [2, 3]];
@a.deepmap({.say; $_}); # OUTPUT: «123»
say @a.raku; # OUTPUT: «[1 [2 3]]»
这是怎么回事?好吧,deepmap
递归地下降到结构中并在每个叶元素上调用函数(这就是为什么它在第二次迭代中打印 2
而不是 [2 3]
的原因)。然后它绑定结果到它正在迭代的插槽。
因此,对于 .clone
,deepmap
向下到达叶节点(例如,2
)并对该值调用 .clone
,得到 2
(Int
)并将其绑定到数组中的位置。
您想要的似乎是 .clone
在 [2 3]
上被调用,而不是 2
。如果是这样,您可以对具有一层嵌套(如上)和 .map(*.clone)
的列表执行此操作;对于更复杂的嵌套,您可以在 map
表达式中使用 duckmap
或测试(或者,正如您发现的那样,在叶值上调用 .clone
并手动添加 Scalar
。 )
如果我正确理解 Raku 文档,数组的元素总是容器化的,即标量。但是,deepmap 方法似乎创建了(内部)具有未容器化元素的数组:
my @a = [1, [2, 3]];
my @b = @a.deepmap: *.clone;
say @b[0].VAR.^name; # Scalar, this is OK
say @b[1].^name; # Array, as expected
say @b[1][0].VAR.^name; # Int, why?
@b[0] = 4; # this works
@b[1][0] = 5; # error: Cannot assign to an immutable value
为什么会这样?
对于上下文,我最初想使用 .deepmap: *.clone
创建一个深拷贝,但我需要该拷贝是可变的。我使用 @a.deepmap: { my $ = .clone }
解决了这个问题,但我仍然很好奇为什么会这样。
If I understand the Raku docs correctly, the elements of Arrays are always containerized, i.e. Scalars.
几乎正确,但不完全正确 – 数组初始化(即使用 [1, 2]
)将值容器化,但这并不意味着元素总是容器化.例如,您可以 explicitly bind a value 到数组中的某个位置。
或者,正如您所发现的,当以不寻常的方式创建数组时,您可能会得到一个非容器化的值。让我们看看 deepmap
在这里做了什么:
my @a = [1, [2, 3]];
@a.deepmap({.say; $_}); # OUTPUT: «123»
say @a.raku; # OUTPUT: «[1 [2 3]]»
这是怎么回事?好吧,deepmap
递归地下降到结构中并在每个叶元素上调用函数(这就是为什么它在第二次迭代中打印 2
而不是 [2 3]
的原因)。然后它绑定结果到它正在迭代的插槽。
因此,对于 .clone
,deepmap
向下到达叶节点(例如,2
)并对该值调用 .clone
,得到 2
(Int
)并将其绑定到数组中的位置。
您想要的似乎是 .clone
在 [2 3]
上被调用,而不是 2
。如果是这样,您可以对具有一层嵌套(如上)和 .map(*.clone)
的列表执行此操作;对于更复杂的嵌套,您可以在 map
表达式中使用 duckmap
或测试(或者,正如您发现的那样,在叶值上调用 .clone
并手动添加 Scalar
。 )