Ruby's one liner "and return"

return, ruby, styles

Solution

To understand oneliners like the one in your question, you need to memorize Ruby operators and their precedence. Or, more precisely, Ruby syntax. You need to see the statements in exactly the same way that Ruby interpreter does. It must become your second nature. Let us now take a look at your one-liner

puts "foo" and return if true

Let us separate the unrelated issues first. Keyword `return` is only applicable inside methods or lambdas and is not really the subject of your question. Furthermore, trailing `if true` is always valid and thus seems unnecessary. To discuss your question in general, let us define method `#bar` and a variable `baz`

def bar
  puts "bar"
end

baz = true

and let us talk about a modified one-liner

puts "foo" and bar if baz

If you have memorized Ruby syntax, you will be able parenthesize the line exactly as Ruby sees it:

( puts( "foo" ) and ( bar ) ) if ( baz )

Trailing `if` behaves like an operator with very low priority. Whole line from the beginning up to `if` is executed only if `baz` is truey, which it is. Therefore,

puts "foo" and bar

gets executed. It is parenthesized as follows:

puts( "foo" ) and ( bar )

You can see that `puts "foo"` is executed first, printing `foo` on the screen and returning `nil`. Since `nil` is falsey, operator `and` just returns it and `bar` on its right side never gets executed.

As for

if baz
  puts "foo"
  bar
end

it is equivalent to:

( puts( "foo" ); bar ) if ( baz )

You can see the difference: `puts "foo"` and `bar` are not joined by `and`, but are independent logical lines. The return value of the first line is discarded and does not affect execution of the second line.

Finally, let us look at what happens upon replacing `and` with `&&`. Because `&&` operator has much higher priority than `and`, oneliner

puts "foo" && bar

becomes

puts( "foo" && bar )

In other words, value of `"foo" && bar` would be computed first, and then passed as an argument to `#puts` method. Because string `"foo"` is considered truey, execution proceeds to `bar`, which prints `"bar"` on the screen and returns `nil`. You can try by yourself that the value of

"foo" && bar

is `nil`, with `"bar"` printed on the screen as a side effect.

puts( "foo" && bar )

thus becomes

puts( nil )

which causes an empty line to be printed on the screen.

The morale is that that one should learn the syntax. Ruby designer made a big step of making the code readable at a glance like a book.

Problem

I recently discovered a Ruby gotcha which I don't completely understand. So, can someone explain to me why these 2 following statements in Ruby are not the same- ``` puts "foo" and return if true ``` VS ``` if true puts "foo" return end ```

Original source