Ruby:使用键/值数组设置新哈希表

4
我正在通过RubyMonk学习Ruby。在服务员机器人问题的解决方案中,有一行代码使用数组创建了一个新哈希表:
o = Hash[*order]

给定

order = [:table, 1, :sandwich, "denver", :drink, "mango shake"]

我理解这里正在做什么以及展开运算符的工作方式。但是,我对创建这个哈希的语法感到困惑。RubyDoc 表示,实际上调用了方法::[],所以我能够确定o = Hash::[](*order)Hash[*order]是同一件事情。但为什么可以将其缩短为Hash[*order]? 这是解析器解释的特殊构造吗?还是有其他原因?在同样的线路上,为什么以下任何一个都不起作用呢?
o = Hash.new
o.[](*order)

或者

o = Hash.new
o[*order]

甚至像这样 o = {}[*order]

我知道这些代码 不应该 起作用;但我不确定为什么。我认为我对使用未先实例化哈希的 Hash[*order] 的用法感到困惑。这是类方法和实例方法之间差异的示例吗?

(顺便说一句,我觉得 o = {*order} 应该可以工作,但它并不起作用。)

有人能解释一下这里发生了什么,以及是否有其他方法将数组中的值添加到哈希中吗?

2个回答

3

这是类方法和实例方法之间差异的示例吗?

没错。

但为什么可以简化为只需要Hash[*order]

Ruby将some_object[]解释为在some_object上调用名为[]的方法。这对哈希表并不特殊,您可以在自己的任何类中实现[]方法并使用该语法。

有人能解释一下这里发生了什么,并且是否有其他方法可以将数组中的值添加到哈希表中?

Hash[*order]调用一个类方法(Hash#[]),它创建一个新的哈希表。 o.[](*order)由于与无法调用new相同的原因而无法工作:在其上调用{}new没有任何意义。 您不能在类的实例上调用类方法。

您可以使用merge添加值:

o = Hash.new
o.merge(Hash[*order])

o = {*order}不能使用,因为{}是哈希字面量的语法,将*order放在其中没有意义。

Hash(*order)Kernel#Hash方法,只接受一个参数。


谢谢,这很有帮助。那么为什么不能使用Hash(*order)呢?我对如何在这里使用方括号感到困惑。 - user428517
2
@sgroves 这个语法调用了Kernel#Hash,该方法在我更新的答案的最后一行有链接。 - Darshan Rivka Whittle
3
Hash[]是一个方便的类方法,类似于调用object[]Hash[]是不同的方法。查看Hash类文档,找到这两个不同的[]方法。此外,在语言中,[]是一种特殊的解析情况,它基本上执行的是object.[](args) - Azolo
啊,谢谢 Azolo。知道 [] 对解释器有特殊意义让我明白了。 - user428517

1
当你写Hash(*order)时,实际上是在调用Kernel模块中的Hash方法,这与调用Hash类中的[]方法不同。请查看文档了解Kernel#Hash中发生了什么。

2
Hash(*order) 调用 Kernel#Hash。实际上,Hash[*order] 调用的是与问题中链接的 Hash 公共类方法。 - Darshan Rivka Whittle
谢谢你发现了这个问题。我已经更新了我的答案,因为我本来就应该写成Hash(*order) - mattr-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接