如何指定返回的数组类型?

sid*_*com 7 arrays documentation raku

sub a { my @c = 1, 2, 3, 4;     return @c };
sub b { my $d = [ 1, 2, 3, 4 ]; return $d };

say a().WHAT; # (Array)
say b().WHAT; # (Array)

my @e = a();
my @f = b();

say @e;     # [1 2 3 4]
say @e[1];  # 2

say @f;     # [[1 2 3 4]]
say @f[1];  # (Any)

# valid raku code, no errors messages
Run Code Online (Sandbox Code Playgroud)

这些子例程都返回一个数组,但返回的数组行为不同。在文档中明确子例程返回哪种数组类型的正确表达式是什么?

sub b ( --> Array ) { my $d = [ 1, 2, 3, 4 ]; return $d };
say b().WHAT;       # (Array)
Run Code Online (Sandbox Code Playgroud)
sub b ( --> Scalar ) { my $d = [ 1, 2, 3, 4 ]; return $d };
say b().WHAT;

# Type check failed for return value; expected Scalar but got Array ([1, 2, 3, 4])
#   in sub b at ...
#   in block <unit> at ...
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 8

这完全是关于一个Scalar没有拆箱的。

return $d ---> return @$d

获得相同行为的第一个机会是改变b常规。

您已经写过“这些子例程都返回一个数组,但返回的数组行为不同。”。但是,正如 Holli 所指出的,b而是返回Scalar绑定到$d(它又包含一个数组):

sub b { my $d = [ 1, 2, 3, 4 ]; return $d };
say b().VAR.WHAT; # (Scalar)
Run Code Online (Sandbox Code Playgroud)

你可以通过 "decontainerizing" 来改变它$d,例如通过前置@

sub b { my $d = [ 1, 2, 3, 4 ]; return @$d };
say b().VAR.WHAT; # (Array)

my @f = b();

say @f;     # [1 2 3 4]
say @f[1];  # 2
Run Code Online (Sandbox Code Playgroud)

@f = b() ---> @f = b[]

如果您将 返回的值解容器化b,则会出现第二个问题/机会。

无论b返回什么,@f赋值都会评估被赋值给它的值列表。在列表上下文中,Scalars 保持原样(就像它们在普通 中一样return $d)。因此,如果您更改b为 decontainerize,那么您需要在分配中这样做@f,如果您想要@e并且@f最终结果相同。

这一次你不能只是@准备这样做。因为那会拼写@b——Raku 会将其解释为一个@b变量。

一种选择是 write @f = @(b()),但这会很丑陋/不习惯。另一种选择是编写@f = b[]. 这利用了b调用中的括号是多余的这一事实。Appending [](“zen slice”)与 writing 具有相同的效果@(b),但少一个字符。

因此,要在列表分配中解容器,您可以编写:

sub b { my $d = [ 1, 2, 3, 4 ]; return $d };
say b().VAR.WHAT; # (Scalar)

my @f = b[];

say @f;     # [1 2 3 4]
say @f[1];  # 2
Run Code Online (Sandbox Code Playgroud)

“在文档中说清楚”

在文档 明确哪个数组类型是子例程返回的内容的正确表达式是什么

我不确定您的这个问题是什么意思,即使切换到“返回的内容”也是如此。

我也不确定要在文档中指出什么,即使有任何好的地方可以指出,相对于您的 SO 中的场景。

我确实知道,如果是我,我会发现以下文档部分与您的场景相比令人困惑

  • Holli 链接的标量容器和列表项部分。在我看来,该部分目前是关于Scalar在列表/数组中使用容器,这与我在上面写的第二个问题有关($d在分配给 的 rhs 的列表中@f)。但这与我写的第一个问题无关(return $d来自b例程)。事情正好相反,即在 a 中有一个数组Scalar

  • 标容器部分前面在同一页上。开场白——“虽然类型的对象Scalar在 Raku 中无处不在,但你很少直接将它们视为对象,因为大多数操作都是去容器化的……”对我有用。但是“如果一个例程可以返回一个容器,如果它被标记为is rw”则问题更大。这真的:

my $x = 23;
sub f() is rw { $x };
f() = 42;
say $x;                 # OUTPUT: «42?»
Run Code Online (Sandbox Code Playgroud)

但是,一个不具有标记例行is rw返回容器。可以return像您一样使用该例程:

my $x = 23;
sub f() { return $x };
say f().VAR.WHAT;       # OUTPUT: «Scalar?»
Run Code Online (Sandbox Code Playgroud)

  • @sid_com 已经睡过了,特别是如果你正在编写将 `return @d` 与 `return $d` 对齐的文档,我建议,为了列出上下文,后者被写成 `return @$d` 而不是 ` $d[]`。如果用户使用文档网站搜索字段在文档中搜索 `@`,那么现在的第二个条目是“@ list contextualizer”,这是正确的信息位,而在文档中搜索 `[ ]`,唯一一个甚至远程关闭的条目是最后一个,它确实对imo没有帮助。实际上,人们必须搜索“Zen slices”,但是新手怎么会知道呢? (3认同)