Reputation: 4193
I'm learning Ruby via RubyMonk. In the solution to the waiter robot problem, there's 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's being done here and how the splat operator works. However, I'm confused about the syntax for creating this hash. RubyDoc says that ::[]
is really the method being called, so I was able to determine that o = Hash::[](*order)
is the same thing. But why can this be shortened to just Hash[*order]
? Is this a special construct that gets interpreted by the parser, or is there another reason? Along the same lines, why don't any of the following work?
o = Hash.new
o.[](*order)
or
o = Hash.new
o[*order]
or even something like o = {}[*order]
I know these shouldn't work; I'm just not sure why. I think I'm confused by the usage of Hash[*order]
without first instantiating a hash with Hash.new
. Is this an example of the difference between class methods and instance methods?
(As a side note, it seems to me that o = {*order}
should work, but it doesn't.)
Can someone explain what's going on here, and if there are alternate ways to add values from an array into a hash?
Upvotes: 4
Views: 471
Reputation: 5821
When you write Hash(*order)
you're actually calling 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's going on under the hood there.
Upvotes: 1
Reputation: 34031
Is this an example of the difference between class methods and instance methods?
Exactly.
But why can this be shortened to just Hash[*order]
?
Ruby interprets some_object[]
as a call to the method named []
on some_object
. This isn't special for Hashes, you can implement a []
method in any class of your own and use that syntax.
Can someone explain what's going on here, and if there are alternate ways to add values from an array into a hash?
Hash[*order]
calls a class method (Hash#[]
) which creates a new Hash. o.[](*order)
doesn't work for the same reason you can't call new
on it: {}.new
doesn't make any sense. You can't call a class method on an instance of the class.
You can add values with merge
:
o = Hash.new
o.merge(Hash[*order])
o = {*order}
doesn't work because {}
is the syntax for a Hash literal, and putting *order
in there doesn't make sense.
Hash(*order)
is Kernel#Hash, a method that expects only one argument.
Upvotes: 3