raku - 对聚合中包含的列表感到困惑,也许是上下文问题?

标签 raku

乐道版 2020.01

我正在编写一些一次性代码,并没有费心去实现一个类,只是使用了一个类似工作的哈希。我发现列表有一些令人惊讶的行为。

class Q1 {}
class R1 {
    has Str $.some-str is required;
    has @.some-list is required;
}

my $r1 = R1.new(
    some-str => '…',
    some-list => (Q1.new, Q1.new, Q1.new)
);

# hash as poor man's class
my $r2 = {
    some-str => '…',
    some-list => (Q1.new, Q1.new, Q1.new)
};

multi sub frob(R1 $r1) {
    for #`(Array) $r1.some-list -> $elem {
        $elem.raku.say;
    }
}

multi sub frob(Hash $r2) {
    for #`(List) $r2<some-list> -> $elem {
        $elem.raku.say;
    }
}

frob $r1;
# OK.
# Q1.new
# Q1.new
# Q1.new

frob $r2;
# got:
# (Q1.new, Q1.new, Q1.new)

# expected:
# Q1.new
# Q1.new
# Q1.new
frob(Hash …)当我调用 .flat 时,按预期工作或 .list在列表中(即使它已经是列表‽)。

我试图制作一个最小的测试用例,但这与 AFAICT 相同。
for [Q1.new, Q1.new, Q1.new] -> $elem {
    $elem.raku.say;
}

for (Q1.new, Q1.new, Q1.new) -> $elem {
    $elem.raku.say;
}

我已经多次阅读有关 List 和 Scalar 的文档,但我仍然无法从我的观察中理解。为什么我必须在Hash中特殊对待列表,而不是在类中?

最佳答案

for不会循环逐项列出的值。

当您将某些东西放在标量容器中时,它会逐项列出。

sub foo ( $v ) { # itemized
  for $v { .say }
}
sub bar ( \v ) {
  for v { .say }
}

foo (1,2,3);
# (1 2 3)

bar (1,2,3);
# 1
# 2
# 3

Hash 中的元素也是一个标量容器。

my %h = 'foo' => 'bar';

say %h<foo>.VAR.^name;
# Scalar

因此,如果您将列表放入哈希中,它将被逐项列出。

my %h;

my \list = (1,2,3);
%h<list> = list;

say list.VAR.^name;
# List
say %h<list>.VAR.^name;
# Scalar

因此,如果您想遍历这些值,则必须对其进行去项目化。

%h<list>[]
%h<list><>
%h<list>.list
%h<list>.self

@(%h<list>)

given %h<list> -> @list { … }

my @list := %h<list>;

(my @ := %h<list>)  # inline version of previous example

你可以通过绑定(bind)来避免这个标量容器。

%h<list> := list;

(这会阻止 = 运算符处理该哈希元素。)

如果你注意到在类对象中你用 @ 定义它不是 $
class R1 {
    has Str $.some-str is required;
    has @.some-list is required;
}

如果您将其更改为 $并标记rw它将像哈希示例一样工作

class R2 {
    has Str $.some-str is required;
    has List $.some-list is required is rw;
}

my $r2 = R2.new(
    some-str => '…',
    some-list => (1,2,3),
);

for $r2.some-list { .say }
# (1 2 3)

它必须是 $变量,否则它不会在标量容器中。
它还必须标记为 rw以便访问器返回实际的标量容器,而不是去项目化的值。

关于raku - 对聚合中包含的列表感到困惑,也许是上下文问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60053587/

相关文章:

testing - 更改 $*DISTRO 值以进行测试

raku - 共享电源可以同时运行多个分接头 block 吗?

class - 正确地将例程传递给对象变量

raku - 为什么 Comma IDE 重启后找不到 `raku` 二进制文件?

date - 为什么 `later` 方法会导致 `Date` 范围内的无限范围?

raku - perl6 'do(file)' 等效

class - 方法在Perl 6中返回正则表达式?

raku - 数组索引是否需要是 native 整数?

regex - 为什么 Perl 6 语法原型(prototype)的正文中不能有任何内容?

raku - 如何在 Perl 6 中实现 Python 的 os.urandom 方法?