1

I'm working my way through a simple tutorial of each vs for loops in Ruby. This is supposed to be one of the simpler examples but for some reason, I don't understand the interaction between the yield statements and the for loop.

class MyEachThing
  def each
    yield 1
    yield 42
    yield 2
    yield 42
    yield 3
  end
end

for i in MyEachThing.new
  p i
end
# >> 1
# >> 42
# >> 2
# >> 42
# >> 3

Yield in this next example that I made up makes sense to me:

def calling
    p yield(45)
end

calling {|i| i*2}

I just don't get how the first example works. Thank you for the help.

inthenameofmusik
  • 617
  • 1
  • 4
  • 16

1 Answers1

2
for i in MyEachThing.new
  p i
end

is similar to this:

MyEachThing.new.each do |i|
  p i
end

which means, you are calling each method on MyEachThing instance and passing i to the block.

And, yield is equivalent to: block.call means, you're calling the block with the passed argument (in this case i).

yield i is equivalent to: block.call(i) and your block is just printing the value of i.

K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
  • @K got it! thank you. the `for` method seems syntactically strange in this scenario. The `each` method makes much more sense to me. – inthenameofmusik Oct 06 '15 at 03:07
  • 1
    yeah, using `each` is preferable as it is more idiomatic. See this post for some more interesting info: http://stackoverflow.com/questions/3294509/for-vs-each-in-ruby – K M Rakibul Islam Oct 06 '15 at 03:14
  • The expressions are not quite "equivalent". If you add `p i` after each `end`, the last value of `i` is printed when using `for`, whereas an exception is raised when `each` is used: `NameError: undefined local variable or method 'i' for main:Object`.... – Cary Swoveland Oct 06 '15 at 04:30
  • 2
    ...The reason is that `for` (as well as `while` and `until`) does not introduce a new scope, so variables assigned values between `for` and `end` are available for viewing or changing after `end`. By contrast, blocks create a new scope, so variables created within a block are not visible outside the block. (However, a variable created before the block and modified within the block is visible after the end of the block.) Generally, coders prefer to use blocks, in part to encapsulate information. – Cary Swoveland Oct 06 '15 at 04:33
  • @CarySwoveland you are right. There is a `subtle` difference and `equivalent` is not the right word, I updated my answer and replaced `equivalent` with `similar` :-) However, the link I posted in my above comment, that explains that different between `each` and `for`. Thanks for your enlightening comment :-) – K M Rakibul Islam Oct 06 '15 at 04:46
  • 2
    @inthenameofmusik: The reason why the "`for` method seems syntactically strange" is because it's a keyword, not a method. – Jörg W Mittag Oct 06 '15 at 09:27