Perl 6中含数组值的哈希:%a{3}与%a{3}.Array为何不同?
Why does iterating
%a{3} vs %a{3}.Array give different outputs in Perl 6? 这个问题的核心在于Perl 6的容器化特性以及哈希类型约束的工作方式,我来给你拆解清楚:
1. 哈希的类型约束与容器化
当你声明my Array %a {}时,你给哈希的值设定了类型约束——每个值必须是Array类型。但Perl 6中哈希的元素都是容器(默认是Scalar容器),这里的约束是指容器内部只能存放Array对象。
当你第一次访问%a{3}这个不存在的键时,Perl 6会自动创建一个符合约束的容器,并在里面初始化一个空Array。这时候%a{3}返回的是这个容器本身,而非容器内部的Array对象。
2. 方法调用的自动解容器
你能顺利对%a{3}执行.push操作,是因为Perl 6在调用方法时会自动解容器(decontainerize)——它会自动访问容器内部的Array对象,然后执行push方法。这就是为什么多次push后,%a{3}.WHAT会显示(Array):WHAT方法同样会自动解容器,返回内部对象的类型,而非容器的类型。如果想查看容器本身的类型,可以用%a{3}.VAR.WHAT,它会显示Scalar[Array](带Array类型约束的标量容器)。
3. 迭代行为的差异
这就是你看到输出不同的关键:
- 当你写
.say for %a{3}时,for循环直接迭代的是容器本身。Perl 6会把这个容器当作单个元素处理,所以.say输出的是容器内部Array的字符串表示:[foo bar baz]。 - 当你调用
%a{3}.Array时,这个方法会显式提取出容器内部的Array对象。此时for循环迭代的是这个Array对象的元素,所以会逐个输出foo、bar、baz。
验证与替代方案
如果你想直接迭代%a{3}的元素,除了调用.Array,还可以用这些方式:
- 显式解容器:
.say for @(%a{3})(用@强制将容器转为数组) - 调用
.list方法:.say for %a{3}.list(.list也会返回容器内部的集合元素)
内容的提问来源于stack exchange,提问作者Eugene Barsky
相关产品推荐
相关产品推荐

