Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IRB - Ruby 1.9.x hash syntax: {if: true} is not equal to {:if => true}

Long story short, I was writing a method that included an options argument, that will do certain stuff if the value for the key :if, evaluated to true. When I trying the hash in IRB using the new syntax I got a syntax error in IRB, the prompt stays open:

1.9.3p374 :010 > {if: true}
1.9.3p374 :011?>

Using the old syntax, works just fine:

1.9.3p374 :011 > {:if => true}
 => {:if=>true} 

All keywords that start a statement, exhibit the same behavior. E.g. def, do, module, case

Other reserved words that occur in the middle and class work just fine: else, end

My question is: Is this expected behavior, a bug or a limitation?

like image 325
Leonel Galán Avatar asked Feb 19 '13 20:02

Leonel Galán


1 Answers

It's challenging to reliably and unambiguously parse things in any language. This is especially true when you start using reserved words. And irb has to go beyond that and provide an interactive model on top of the parser, which is even harder. I personally don't think there's too much value in worrying about cases like this, either as a user of the language or as a maintainer. In my mind, it's better to simply figure out what works and avoid getting into these situations if possible.

You can see some similar behaviors in plain Ruby, outside irb. For example:

puts({if: true})  # no problem, behaves as expected in Ruby 1.9.3.
puts {if: true}   # raises a syntax error in Ruby 1.9.3

To answer your question, is it "expected behavior, a bug or a limitation", I'd say you should ignore irb and compare it to plain Ruby, and if you do this, it works fine. That means it has to be an irb bug.

But is it possible or worthwhile to solve? @coreyward makes a good point in his comment that irb has to delay execution in most cases when it encounters an if. You'd have to look further to know for sure, but you may not be able to unambiguously interpret all cases like this.

My advice: avoid this construct altogether if you can, and don't use reserved words for labels if you can avoid it!

Here's a file you can run with plain Ruby (eg MRI). You should see {:if=>true} in the output to confirm it works.

{if: true}
foo = {if: true}
# if MRI is working, should be able to execute this file without trouble.
p foo
like image 136
Peter Avatar answered Oct 24 '22 02:10

Peter