4

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?

Community
  • 1
  • 1
mhively
  • 93
  • 6

1 Answers1

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()

Phlip
  • 5,253
  • 5
  • 32
  • 48
  • This ^ or assigning the hash to a variable and then logging it as `puts varname` makes the broken ones work as well. – Alex Dovzhanyn May 10 '18 at 19:36
  • So I guess the takeaway from this is that hash literals can be confused with ruby blocks? – mhively May 10 '18 at 22:29
  • yes; and that Ruby is slightly space sensitive. `puts()` differs from `puts ()`. – Phlip May 10 '18 at 22:55
  • 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. :P – GrandOpener Mar 22 '19 at 20:20