Block linking in Enumerable's each, allowed?

each, enumerable, ruby

Solution

Actually I think the following version is even more commonly seen:

def each
  @items.each { |i| yield i }
end

This is equivalent to your first code sample. There is however a subtle difference between this and your second version:

class Test
  def initialize(items)
    @items = items
  end

  def each1
    @items.each { |i| yield i }
  end

  def each2(&block)
    @items.each(&block)
  end
end

Observe:

irb(main):053:0> Test.new([1,2,3]).each2
=> #<Enumerator: [1, 2, 3]:each>
irb(main):054:0> Test.new([1,2,3]).each1
LocalJumpError: no block given (yield)
    from (irb):43:in `block in each1'
    from (irb):43:in `each'
    from (irb):43:in `each1'
    from (irb):54
    from /usr/bin/irb:12:in `<main>'

The version that delegates the block to the underlying iterable actually returns an enumerator if no block is given, which is very nice. It allows us to write stuff like this:

irb(main):055:0> Test.new([1,2,3]).each2.map { |x| x + 1 }
=> [2, 3, 4]

To achieve the same with our explicit version, we'd have to adapt it like this:

def each1
  return enum_for(:each1) unless block_given?
  @items.each { |i| yield i }
end

Which is even more verbose. Bottomline: Delegate the block to an underlying enumerable whenever possible, to save yourself from code duplication and from subtle gotchas like these.

By the way, now that you realize the two-folded nature of your `each` method, it would make sense to name it differently. For example, you could follow the example of methods like `String#chars` or `IO#lines` and call your method `items`:

def items(&block)
  @items.each(&block)
end

Problem

In many cases over internet i seen examples of `each` method for Enumerable as: ``` def each(&block) @items.each do |item| block.call(item) end end ``` Why people not using this one: ``` def each(&block) @items.each(&block) end ``` Is there any differences?

Original source