Felipe
Felipe

Reputation: 11887

Shouldn't these two Ruby snippets work the same way?

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?

Upvotes: 2

Views: 252

Answers (3)

jtbandes
jtbandes

Reputation: 118681

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

Upvotes: 2

Theo
Theo

Reputation: 132862

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.

Upvotes: 3

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230346

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.

Upvotes: 1

Related Questions