M.ElSaka
M.ElSaka

Reputation: 1294

strange syntax error?

I tried to run this simple code in an IRB session, but I got this error:

[9] pry(main)> puts {x: 1}
SyntaxError: unexpected ':', expecting '}'
puts {x: 1}
        ^

I know that I can run the same code like this:

[12] pry(main)> y = {x: 1}
=> {:x=>1}
[13] pry(main)> puts y
{:x=>1}

or:

[14] pry(main)> puts "",{x: 1}
{:x=>1}

What is that the problem in the first case?

Upvotes: 0

Views: 92

Answers (3)

Jörg W Mittag
Jörg W Mittag

Reputation: 369420

Curly braces can denote either a block literal or a Hash literal. In this case, it is interpreted as a block literal, and x: 1 is not a syntactically valid Ruby expression.

You can provide the argument list with parentheses to resolve this ambiguity:

puts({x: 1})

Or alternatively, Ruby allows you to leave out the curly braces if the last argument to a method is a Hash:

puts(x: 1)

And in that case, you can again leave out the parentheses, because there is no confusion with a block:

puts x: 1

Your last example works, because the comma tells the parser that the argument list isn't finished yet and what follows couldn't possibly be a block.

Upvotes: 4

Nikola
Nikola

Reputation: 704

Ruby thinks your passing a block. For passing a hash, try:

puts({x: 1})

or

puts(x: 1)

Upvotes: 0

Hauleth
Hauleth

Reputation: 23556

In the first case {} is parsed as a block. In the second it is parsed as a hash.

Example:

def foo(opts = nil, &block)
  p opts
  p block
end

foo { 'a' } #=> nil #<Proc:0x007f12144f7f68@(pry):12>
foo({a: 'a'}) #=> {:a=>"a"} nil
foo a: 'a' #=> {:a=>"a"} nil

Upvotes: 1

Related Questions