Ruby: setting a new hash with an array of keys / values

I am learning Ruby through RubyMonk. In solving the problem of a robot waiter, there is a line of code that creates a new hash using an array:

o = Hash[*order] 

given

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

I understand what is being done here and how the splat operator works. However, I am confused by the syntax for creating this hash. RubyDoc says that ::[] is really a callable method, so I was able to determine that o = Hash::[](*order) is the same. But why can this be reduced to just Hash[*order] ? Is this a special construct that is interpreted by the parser, or is there another reason? Along the same lines, why not one of the following works?

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

or

 o = Hash.new o[*order] 

or even something like o = {}[*order]

I know this should not work; I just don’t know why. I think it bothers me to use Hash[*order] without the first hash instance with Hash.new . Is this an example of the difference between class methods and instance methods?

(As a note, it seems to me that o = {*order} should work, but it is not.)

Can someone explain what is happening here and are there alternative ways to add values ​​from an array to a hash?

+4
source share
2 answers

Is this an example of the difference between class methods and instance methods?

That's right.

But why can this be shortened to Hash[*order] ?

Ruby interprets some_object[] as a method call with the name [] on some_object . This does not apply to hashes; you can implement the [] method in any class and use this syntax.

Can someone explain what is happening here and are there alternative ways to add values ​​from an array to a hash?

Hash[*order] calls the class method ( Hash#[] ), which creates a new Hash. o.[](*order) doesn't work for the same reason you can't call new : {}.new doesn't make any sense. You cannot call a class method on an instance of a class.

You can add values ​​with merge :

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

o = {*order} does not work, because {} is the syntax for the hash literal, and marking *order does not make sense there.

Hash(*order) Kernel # Hash is a method that expects only one argument.

+3
source

When you write Hash(*order) , you actually call the Hash method in the Kernel module, which is not the same as calling the [] method in the Hash class. See the docs for Kernel#Hash to see what happens under the hood.

+1
source

All Articles