如何判断某个东西是否是Perl 6容器?

bri*_*foy 5 containers perl6

我没有任何有用的理由知道这一点,但我想知道我是否有一个名称$x,如果这是一个标量变量(可变的东西)或仅仅是某个东西的名称(不可变的东西).我不想做任何事; 这是好奇心.

我正在玩这样的事情:

my @a  = 'a', ('b', 'c' );
my @b  = 'd', 'e', 'f', @a;

my @ab = @a, @b, ( 1, 2 );

for @ab {
    put "name: {.^name} VAR: { .VAR.^name }";
    when .VAR.can('FETCH') { put "Container: $_" }
    when .VAR.can('STORE') { put "Container: $_" }
    when Scalar            { put "Scalar container: $_" }
    when Array             { put "Array Container: $_" }
    default                { put "Object: $_"    }
    }
Run Code Online (Sandbox Code Playgroud)

我明白了:

name: Array VAR: Scalar
Array Container: a b c
name: Array VAR: Scalar
Array Container: d e f a b c
name: List VAR: Scalar
Object: 1 2
Run Code Online (Sandbox Code Playgroud)

我可以看到我可以匹配类型Array类型匹配,但我认为检查某些东西可以FETCHSTORE将是正确的匹配.

Chr*_*oph 4

不确定您在这里问什么,但根据您的输入,输出符合预期。

用于澄清的简化示例:

my (@a, @b, @c);
my @ab = @a, @b, @c;

for @ab {
    say "{.^name} contained in a {.VAR.^name}";
}
Run Code Online (Sandbox Code Playgroud)

这将输出

Array contained in a Scalar
Run Code Online (Sandbox Code Playgroud)

@a无论、@b和的内容,三遍@c

请记住,Perl6 中没有隐式扁平化,并且(非本机数组的)数组可变性是通过将其元素放入标量容器中来实现的。


鉴于对您的问题的编辑,也许以下代码将进一步阐明发生了什么:

# make argument raw so binding won't mess with it
sub info($_ is raw) {
    dd $_;
    put "  value type: {.^name}";
    put "  VAR type: {.VAR.^name}";
    put "  can fetch: {so .VAR.can('FETCH')}";
    put "  can store: {so .VAR.can('STORE')}";
}

my \values = 42, my $ = 42, [1, 2], (1, 2);
info $_ for values;

put "\n";

# put values in array, which wraps them in a scalar container
info $_ for [values];
Run Code Online (Sandbox Code Playgroud)

请注意,只有列表和数组可以STORE(但不能FETCH),而标量两者都不能。

这可能会令人惊讶:首先,我们可能期望任何可分配的内容都应该提供STORE.

查看实现,我们发现对于带有 sigil@和 的变量%,我们确实调用STORE,但对于带有 sigil 的变量则不然$。如果我们进一步深入这个兔子洞,我们最终会到达虚拟机级别的容器规范Proxy,这就是如何实现对标量容器的分配(或对象方法的调用STORE)。