如何解决分配给列表容器混淆
我可能患有大脑衰退,但根据有关项目和列表分配的文档 (https://docs.raku.org/language/variables#Item_and_list_assignment ),
分配给列表容器(列表上下文)总是触发列表分配。
然而,这似乎与我从代码中得到的内容相冲突(这里在 raku repl 中复制)..
Welcome to ??????™ v2020.10.
Implementing the ????™ programming language v6.d.
Built on MoarVM version 2020.10.
这是一个错误,还是我误解了意图......?
watch:{
todoItem:{
deep: true,handler(){
this.saveTodoAction(this.todoItem);
}
}
},
解决方法
TL;DR 如果非本地项通过赋值可变,则它是 Scalar
。列表分配不会展平 Scalar
项。 [1]
暗示
考虑这个代码:
my %map = :a;
%map<a> = 42;
say %map<a>; # 42
该作业有效,因为:
say %map<a>.VAR.WHAT; # (Scalar)
“列表分配”
考虑这个代码:
my $scalar = 1,2; # Useless use of constant integer 2
say $scalar; # 1
my @list1 = 1,2; # "list assignment",so RHS is iterated
say @list1; # [1 2]
所以这是项目分配和列表分配之间的一个区别。
my @list3 = [1,2]; # Again,RHS is iterated
say @list3; # [1 2]
my @list2 = (1,2); # Again,RHS is iterated
say @list2; # [1 2]
my @list4 = 1,(2,3); # Again,RHS is iterated. Second element stays as a `List`.
say @list4; # [1 (2 3)]
my @list5 = 1,[2,3]; # Again,RHS is iterated. Second element stays as an `Array`.
say @list5; # [1 [2 3]]
如果 RHS 上只列出了一项,并且它不是 Scalar
,则列表分配会将其展平。但在所有其他情况下,列表分配不会使项目变平。
my @list6 = $[1,2]; # RHS is a `Scalar`. So it doesn't get flattened.
say @list6; # [[1 2]]
我很困惑!
高尔夫的情况在Q:
my Str @res = %( :a[42,99] )<a>;
这会产生同样的错误。
因为:
say .VAR.WHAT given :a[42,99]<a>; # (Array)
say .VAR.WHAT given (% = :a[42,99])<a>; # (Scalar)
脚注
[1] 当猜测产生惊喜,而您将其转化为学习时,您就意识到并理想化了对ERNing 的投资。
,注意:阅读@raiph
s answer不会出错。不过,我会尝试解释这里发生的事情并提出可能的解决方案。
在 Raku 中,context 就是一切。这意味着不同的上下文在不同的上下文中触发,这意味着您正在使用的数据结构具有不同的装箱或拆箱功能。
让我们看看这个
my %syns-by-name = %(Bq => ["Bq","becquerel","becquerels"],C => ["C","coulomb","coulombs"],)
我们确实知道我们处于“关联”上下文中,因为百分比标记了等号的两侧。我们甚至不需要它在右手边:
my %syns-by-name = Bq => ["Bq","coulombs"]
因为,看看 lhs,它仍然是一个关联,所以我们知道我们手中有什么。在这个上下文中使用相同的rhs代码:
my @list-of-signs = Bq => ["Bq","coulombs"] # [Bq => [Bq becquerel becquerels] C => [C coulomb coulombs]]
将产生对列表。因此,我们会检查您在 OP 中提到的内容:
分配给列表容器(列表上下文)总是触发列表分配。
是真的。这是一个“列表”容器,我们仅根据上下文将 rhs 转换为列表。这里发生的事情没有歧义:rhs 是一个逗号分隔的列表,lhs 是一个位置。就这样吧。
您的代码中的情况略有不同。如果我们使用 2020.12 可能会澄清一点
my %syns-by-name = Bq => ["Bq","coulombs"]
my Str @res = %syns-by-name{'Bq'};
# Type check failed in assignment; expected Positional[Str] but got Array ($["Bq",...)
乍一看可能看不出区别,所以我会在这里强调:
绑定类型检查失败;预期的 Positional[Str] 但得到了 Array ($["Bq",...)
这表明数组是itemized,它被装箱,以便它可以放入一个类似于标量的东西,比如散列键的值。默认情况下,散列值是标量,这组成了它们的定义:
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 问题来解决它。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。