gpt4 book ai didi

arrays - 什么算作 Slip 的 "outer list"?

转载 作者:行者123 更新时间:2023-12-04 12:19:16 25 4
gpt4 key购买 nike

docs for Slip提到“Slip 是一个列表,它会自动展平为外部列表(或其他类似列表的容器或可迭代对象)”。基于这个定义,这是完全合理的:

dd my @a = 1, |(2, 3); # OUTPUT: «Array @a = [1, 2, 3]»
但是,我对以下内容感到惊讶:
dd my @b = do {@a[2] := |(3, 4); @a} # OUTPUT: «Array @b = [1, 2, slip(3, 4)]»
我本来以为 slip(3, 4)扁平化为@b,而不是保持 slip . (也就是说,很惊讶 @a[2] := |(3, 4) 没有与 @a.splice(2, 1, [3, 4]) 相同的语义。)
list assignment在这里被视为一种特殊情况,其语义与普通 Slips 不同?或者是否有关于 Slips/Lists/Arrays 的语义使这一切都保持一致而无需特殊大小写分配?

最佳答案

Slip 是一个列表 那个可以 展平成一个外部序列。
所以下面产生了一个扁平化的列表。

1, |(2, 3)
这是因为逗号 , .
如果将该列表插入到给定位置的数组中,则是将该列表插入到单个给定位置的数组中。
@a[0] = 1, |(2, 3); # [(1,2,3),]
如果你插入一个 Slip 也会发生同样的事情,因为 Slip 只是 List 的一个子类。
@a[0] = |(2, 3); # [slip(2,3),]
事实上,Slip 几乎完全只是一个列表。这是来自 Rakudo 的 Slip 代码。
# A Slip is a kind of List that is immediately incorporated into an iteration
# or another List. Other than that, it's a totally normal List.
my class Slip { # is List

# XXX this makes an empty Slip undefined?
multi method defined (Slip:D: --> Bool:D) { self.Bool }

multi method Slip(Slip:D:) { self }
method CALL-ME (+args) { args.Slip }
multi method raku(Slip:D: --> Str:D) {
nqp::if(
nqp::eqaddr(self,Empty),
'Empty',
nqp::stmts(
(my str $guts = callsame),
nqp::if(
nqp::eqat($guts,'$',0), # we're itemized
nqp::concat('$(slip',nqp::concat(nqp::substr($guts,1),')')),
nqp::concat('slip',$guts)
)
)
)
}
multi method List(Slip:D: --> List:D) {
my $list := nqp::create(List);
nqp::bindattr($list,List,'$!todo',nqp::getattr(self,List,'$!todo'))
if nqp::isconcrete(nqp::getattr(self,List,'$!todo'));
nqp::bindattr($list,List,'$!reified',nqp::getattr(self,List,'$!reified'))
if nqp::isconcrete(nqp::getattr(self,List,'$!reified'));
$list
}
}
这只会使 4 个功能起作用。
  • |().defined这是定义的吗?
    如果它包含元素是,否则不是。
    ( Empty 肯定是未定义的,但 |(,)slip() 可能应该被定义。这个方法只是说两者都是未定义的。)
  • Slip((1,2))将现有列表强制转换为 Slip。
  • Empty.raku/|(,).raku打印值以便它可能被评估。Empty是一个空 Slip 的特定实例,它在运行时有一些特殊的处理。
  • |().List获取列表而不是单据。
    这需要在这里,因为 Slip 是 List 的子类,所以通常它只会返回自身。

  • 所有这些都与 Slip 扁平化为 List 无关。
    请注意,即使顶部的注释也说明它只是一个普通列表。

    如果您使用列表(ish,在本例中为 ListRange )作为索引,您可以将其展平。
    @a[2,  ] = |(3,4); # [Any, Any, 3]
    @a[2, 3] = |(3,4); # [Any, Any, 3, 4]
    @a[2..3] = |(3,4); # [Any, Any, 3, 4]
    通过使用列表索引,您告诉 Raku @a[…] 的结果。操作是一个列表,而不是单个值。
    这与右值是 Slip 无关。它与右值是 List 的子类有关。

    更明确一点。
    my $l-value := @a[2]; # contains the actual Scalar object in the array
    my $r-value := |(3,4);
    $l-value = $r-value;
    这与您的代码所做的基本相同
    @a[2] = |(3,4);
    @a[2] =是两个独立的操作。索引,然后分配 @a[2]返回标量容器,然后是 =将右侧的值分配到该单个容器中。
    为了使 Slip 变平,分配需要访问 Array 本身。它没有的东西。它只能访问单一的标量容器。所以它将 Slip 插入到它确实拥有的标量中。 (实际上,赋值并不真正知道标量甚至是数组中的成员。)
    当你绑定(bind)时,你会做一些稍微不同的事情。问题是绑定(bind)应该低于常规分配的级别。所以更有可能只是插入一个点而不是变平。
    要让它做任何不同的事情, @a[2]必须返回一个知道如何将 Slip 展平为数组的代理。

    如果您真的想这样做,请使用 splice因为它有对数组的引用。
    my @a = 1, |(2, 3);
    @a.splice: 2, 1, |(3,4);
    同样,由于 Slip,这并不特别。

    关于arrays - 什么算作 Slip 的 "outer list"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67855287/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com