Ruby: rules for implicit hashes

为君一笑 提交于 2019-12-25 02:38:29

问题


Why second output shows me only one element of Array? Is it still Array or Hash already?

def printArray(arr)
    arr.each { | j |
        k, v = j.first
        printf("%s %s %s \n", k, v, j)
    }
end

print "Array 1\n"
printArray( [
                {kk: { 'k1' => 'v1' }},
                {kk: { 'k2' => 'v2' }},
                {kk: { 'k3' => 'v3' }},
            ])


print "Array 2\n"
printArray( [
                kk: { 'k1' => 'v1' },
                kk: { 'k2' => 'v2' },
                kk: { 'k3' => 'v3' },
            ])

exit

# Output:
#
# Array 1
# kk {"k1"=>"v1"} {:kk=>{"k1"=>"v1"}} 
# kk {"k2"=>"v2"} {:kk=>{"k2"=>"v2"}} 
# kk {"k3"=>"v3"} {:kk=>{"k3"=>"v3"}} 
# Array 2
# kk {"k3"=>"v3"} {:kk=>{"k3"=>"v3"}}

回答1:


Ruby interpreted the second example as an array with a single hash as its element (the curly braces are implied). It is equivalent to this:

[{ kk: { 'k1' => 'v1' }, kk: { 'k2' => 'v2' }, kk: { 'k3' => 'v3' }}]

Only the last 'kk' is shown because hashes can't have duplicate keys; only the last one sticks.

If you want an array with multiple hashes as elements, you need to use the syntax like on your first example.


More examples on which ruby implies a hash start:

# Only argument on method calls
def only_arg(obj)
  puts obj.class
end

only_arg(bar: "baz")  # => Hash

# Which is equivalent to:
only_arg({bar: "baz"}) # => Hash


# Last argument on method calls
def last_arg(ignored, obj)
  puts obj.class
end

last_arg("ignored", bar: "baz") # => Hash

# Which is equivalent to:
last_arg("ignored", { bar: "baz" }) # => Hash


# Last element on an array
def last_on_array(arr)
  puts arr.last.class
end

last_on_array(["something", "something", bar: "baz"]) # => Hash

# Which is equivalent to:
last_on_array(["something", "something", { bar: "baz" }]) # => Hash


来源:https://stackoverflow.com/questions/19870295/ruby-rules-for-implicit-hashes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!