Home > Software engineering >  Why "puts {a: 1}" is a violation of Rubocop
Why "puts {a: 1}" is a violation of Rubocop

Time:07-28

The expression { a: 1 } is not a problem,

but Rubocop's point( Lint/Syntax: unexpected token tCOLON(Using Ruby 3.1 parser; configure using TargetRubyVersion parameter, under AllCops) ) appears in the expression puts { a: 1 }.

Does anyone know why this statement is against the rules? If you have a reference, I would appreciate it if you could also give me the URL of it.

I use rubocop version 1.24.1 and set TargetRubyVersion in .rubocop.yml. ruby versions 2.7, 3.0 and 3.1 were all tested with the same result.

CodePudding user response:

Braces in Ruby are used for two things: blocks and hashes. And the Ruby parser isn't going to perform infinite lookahead to determine which one it's looking at. If the current syntactic context accepts a block, Ruby assumes the thing you've given it with braces is a block.

puts { a: 1 }

First, we parse puts. It's an identifier, and it's not a local variable, so we'll assume it's a method on the current (main) object. Now we see {. It could be either a hash or a block. And we just parsed an identifier starting a function call, so a block would make sense here. Let's parse it as a block.

Next we see a. Okay, that's fine. A block with no arguments, and we've got an identifier called a. Again, it's not a local variable, so it must be a method on main. Then we see : and that doesn't work. There's no way a : can appear at this point in the syntax, so it's an error. Ruby does not go back and try the "hash" option; it's already committed completely to parsing a block, and that failed.

To call puts with a single hash argument, use parentheses to disambiguate.

puts({ a: 1 })
  • Related