Why does a space changes the outcome?

Hello! I am new to ruby and have been playing around. I came across this situation and dont understand why:

irb(main):043:0> puts(“hello”) || true
hello
=> true
irb(main):044:0> puts (“hello”) || true
hello
=> nil

why does the space between puts and hello changes the return value? puts("x) or puts (“x”) both return nil so I dont understand whats going on. I would really appreciate some help!

I think it’s to do with precedence. Replacing your true with another print:

2.7.2 :014 > puts("hello") || puts("bye")
hello
bye
 => nil 
2.7.2 :015 > puts ("hello") || puts("bye")
hello
 => nil

Ruby prefers not to have a space between the function and its bracketed arguments, so I think the second case is working like:

2.7.2 :016 > puts(("hello") || puts("bye"))
hello
 => nil

i.e. it’s printing the result of ("hello") || puts("bye"), which is the string “hello”.

yes, after experimenting a little more I see that. it seems that the space breaks the statment. But I dont really know.

irb#1(true):003:0> puts(“hello”)||true
hello
=> true
irb#1(true):004:0> puts(“hello”);true
hello
=> true


both behave the same, but I dont know if it is why I think it is.
Anyway thanks for the help! It is not important I just found it intersting!

I have written before about this thing. When you call a method, you should always put the parentheses immediately after the method name. Consider these cases:

  1. puts("Hello", 5): In this case, you are calling Kernel.puts with the argument “Hello” and 5. It’s same as puts "Hello", 5.

  2. puts ("Hello", 5): In this case, you are calling Kernel.puts but not passing “Hello” and 5, as an argument directly, instead, the (…) breaks it. In this case, you get SyntaxError. The right way will be puts("Hello", 5).

But if you were to write puts (5), you don’t pass it as argument to puts, immediately, the code inside the parentheses is evaluated first, and then it’s sent as an argument to puts.

Now in your case, you are using short-circuit evaluators, or (||) in this case. So in:

Case 1: You call puts with hello. puts writes to the standard output and returns nil. Which is equivalent of doing nil || true, in that case, you get true.

Case 2: You call puts with "Hello" || true. In Ruby everything except nil and false are truthy. So “Hello” string is truthy, so || will only return the first expression and not the 2nd one. If you do "Hello" && true, then you get true. Anyway, then the returned "Hello" is sent to puts. It’s just like doing puts("Hello" || true).

2 Likes

Thanks for the amazing answer, It is super clear now! Coming from other pl I found really weird that ruby lets me use puts () #method with a space# like that so I imagined something was going on under the hood!