Ruby syntax error when try to puts literal hash
Asked Answered
O

1

5

Could someone explain to me why in ruby console (version 2.3.4) trying to print hashes these work:

puts({a: 'a', b: 'b'})
puts(a: 'a', b: 'b')
puts a: 'a', b: 'b'
puts [a: 'a', b: 'b']  <<< array length 1 with value of hash
puts Hash[a: 'a', b: 'b']

but none of these work:

puts {a: 'a', b: 'b'}
puts {:a => 'a', :b => 'b'}
puts{:a => 'a', :b => 'b'}

gives error:

syntax error, unexpected ',', expecting '}'

puts {a: 'a', b: 'b'}

_ _ _ _ _ _^

And these:

 puts {:a => 'a'}
 puts {a: 'a'}
 puts{a: 'a'}

also error with:

syntax error, unexpected =>, expecting '}'

puts {:a => 'a'}

_ _ _ _ _ ^

It was my understanding () around functions were entirely optional and up to the developer's style preferences.

And that {} around hashes were mostly optional, but never required to NOT be used.

I could understand if the interpreter were confused between 1 or 2 hashes (since puts takes 1+ arguments), but it just dies.

To make matters worse: these work:

 puts({a: 'a', b: 'b'}, [:d, :e])
 puts ({a: 'a', b: 'b'})

but these do not:

 puts ({a: 'a', b: 'b'}, [:d, :e])
 puts (Hash[a: 'a', b: 'b'], [:d, :e])

Can anyone explain what is actually going on behind the scenes?

Oldwife answered 10/5, 2018 at 19:7 Comment(0)
V
6

Ruby has a glitch because it's too permissive with parentheses. You can leave them off nearly anything, but...

puts{} parses as "call puts with a block {}." A block, in turn, must contain complete statements, not a comma , separated list. So you get the wrong syntax error.

The fix is just puts({})

Next, puts () parses as "puts followed by a single argument, in parentheses." So, again, the parser cannot deal with comma , inside the parenthesis. The fix is to take out the space: puts()

Varistor answered 10/5, 2018 at 19:10 Comment(4)
This ^ or assigning the hash to a variable and then logging it as puts varname makes the broken ones work as well.Landslide
So I guess the takeaway from this is that hash literals can be confused with ruby blocks?Oldwife
yes; and that Ruby is slightly space sensitive. puts() differs from puts ().Varistor
IMO the takeaway from this is that making parenthesis contextually optional was just a bad idea in the first place. No hate on Ruby; it's a great language; I've just never been sold on this particular choice. :PAkkerman

© 2022 - 2024 — McMap. All rights reserved.