注意:阅读@raiphs answer 不会出错。不过,我将尝试解释这里发生的情况并提出可能的解决方案。
在 Raku 中,context 就是一切。这意味着在不同的上下文中触发不同的上下文,这意味着您正在使用的数据结构具有不同的装箱或拆箱功能。
让我们看看这个
my %syns-by-name = %(Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"],)
我们确实知道我们处于“关联”上下文中,因为百分比标记在等号的两边。我们甚至不需要它在右手边:
my %syns-by-name = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"]
因为,看 lhs,它仍然是一个联想,所以我们知道我们手中有什么。此上下文中的自同 rhs 代码:
my @list-of-signs = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"] # [Bq => [Bq becquerel becquerels] C => [C coulomb coulombs]]
将产生一个配对列表。因此,我们检查您在 OP 中提到的内容:
分配给列表容器(列表上下文)总是触发列表分配。
是真的。这是一个“列表”容器,我们只是根据上下文将 rhs 变成一个列表。这里发生的事情没有歧义:rhs 是一个逗号分隔的列表,lhs 是一个位置。所以你去吧。
您的代码中的情况略有不同。如果我们使用 2020.12 可能会更清楚一点
my %syns-by-name = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"]
my Str @res = %syns-by-name{'Bq'};
# Type check failed in assignment; expected Positional[Str] but got Array ($["Bq", "becquerel", ...)
可能第一眼看不出区别,所以我在这里强调一下:
绑定类型检查失败;预期 Positional[Str] 但得到 Array ($["Bq", "becquerel", ...)
这表明该数组是itemized,它已被装箱,以便它可以放入类似标量的东西中,例如哈希键的值。默认情况下,Hash 值是 Scalar,这包含在它们的定义中:
role Associative[::TValue = Mu, ::TKey = Str(Any)] { }
所以你提到的仍然成立:列表分配被触发,就像在“列表上下文”中一样。但是,单个项目只能通过一种方式转换为列表:通过使其成为列表中的单个元素。如果您仔细查看错误报告,就会发现它在说什么:嘿,您告诉我您要给我一个 Strs 列表。这不是那个!这是(逐项)数组的列表!这有效:
my List @res = %syns-by-name{'Bq'};
# [(Bq becquerel becquerels)]
我们需要做的是“拆箱”这个东西,也就是检索包含在 Scalar 中的 Array。简单易懂:
my Str @res = %syns-by-name{'Bq'}<>;
# [Bq becquerel becquerels]
de-cont operator (which maybe should be called "unbox" or "de-Scalarize" or "de-itemize" operator) 为您做正确的事。然而,这可能不是你想要的。你希望你的数组是数组。然而,事实证明这有点棘手,我需要另一个 SO 问题来解决它。