Search code examples
rubysyntax-errorliteralsputsruby-2.3

Ruby syntax error when try to puts literal hash


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?


Solution

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