Why does `puts(nil or 4)` fail in Ruby?

前端 未结 3 1932
猫巷女王i
猫巷女王i 2021-01-03 22:41

When I do:

puts(nil or 4)

Ruby complains:

SyntaxError: syntax error, unexpected ke         


        
3条回答
  •  抹茶落季
    2021-01-03 23:12

    Short answer

    Because that's how ruby syntax is.

    Longer answer

    and/or keywords were designed to be used in control flow constructs. Consider this example:

    def die(msg)
      puts "Exited with: #{msg}"
    end
    
    def do_something_with(arg)
      puts arg
    end
    
    do_something_with 'foo' or die 'unknown error'
    # >> foo
    # >> Exited with: unknown error
    

    Here or works nicely with ruby's optional parentheses, because of ruby parsing rules (pseudo-BNF).

    In short, an argument list (CALL_ARGS) is a list of ARG, separated by comma. Now, most anything is an ARG (class definitions, for example, through being a PRIMARY), but not an unadorned EXPR. If you surround an expression with parentheses, then it'll match a rule for "compound statement" and, therefore, will be a PRIMARY, which is an ARG. What this means is that

    puts( (nil or 4) ) # will work, compound statement as first argument
    puts (nil or 4)  # same as above, omitted optional method call parentheses
    puts(nil or 4) # will not work, EXPR can't be an argument
    puts nil or 4 # will work as `puts(nil) or 4`
    

    You can read the grammar referenced above to understand exactly how it works.

    BONUS: Example of class definition being a valid ARG

    puts class Foo
           def bar
             puts "hello"
           end
         end, 'second argument'
    
    # >> bar # this is the "value" of the class definition
    # >> second argument
    

提交回复
热议问题