2

In venturing into Ruby, I started toying with things like the way Ruby returns the last thing you've mentioned even if it was not after a return construct. However, why don't these two snippets work the same way? Shouldn't they?

module Enumerable
  def palindrome?
    reversed_self = self.reverse
    self.each_with_index {|el,index|
      unless self[index]==reversed_self[index]
        return false ## <-----
      end
    }
    true
  end
end

all good so far: puts ['foo','bar','baz'].palindrome? prints 'false'

and

module Enumerable
  def palindrome?
    reversed_self = self.reverse
    self.each_with_index {|el,index|
      unless self[index]==reversed_self[index]
        false ## <------
      end
    }
    true
  end
end

puts ['foo','bar','baz'].palindrome? prints 'true' for some reason

What's the science behind this?

3 Answers 3

3

Ruby will return the value of the last executed expression in a method. The false in the second version is not the last expression, there's nothing telling Ruby to stop executing at that point so it will chug along until the method ends.

return is a way to explicitly say to Ruby to stop executing and return a value.

Sign up to request clarification or add additional context in comments.

Comments

2

Not quite! A return from inside a block is different from a return inside a lambda, as mentioned in my answer here. When you return from inside a block, you're returning from the entire method rather than just the block.

We can illustrate this as follows:

return :foo # => LocalJumpError: unexpected return
[1, 2, 3].map { return :foo } # => LocalJumpError: unexpected return
[1, 2, 3].map { :foo } # => [:foo, :foo, :foo]

Normally, this doesn't happen with lambdas:

l = lambda { return :foo }
l.call # => :foo
[1, 2, 3].map { l.call } # => [:foo, :foo, :foo]

But when we try to pass the lambda as a block to the method, the behavior changes back:

[1, 2, 3].map &l # => LocalJumpError: unexpected return

2 Comments

So you mean that when there's a return clause inside a block we return from the block only? I think you got confused in your answer?
No, it's exactly the opposite. A return from inside the block tries to return from the enclosing method. I edited my second sentence to clarify.
1

If no return statement is present, then return value of a function is the last value evaluated. In the second snipped the last value is always true.

First snippet returns early with false. Second does nothing with that false, it's discarded.

4 Comments

It doesn't discard it: assuming the condition is satisfied, the unless..end block will evaluate to the false inside of it. The point is that the return statement will return from the whole method.
@jtbandes: and then value of that unless is discarded :)
Well alright, it's discarded by the each, but not by a property of the language.
@jtbandes: agree, I could have used better wording.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.