13

The Enumerable documentation does not state explicitly that each is an alias for each_entry, but the description of each_entry matches exactly what I would expect from each.

In the examples of both answers new classes are defined, which implement the Enumerable module and define the each method.

Can someone give an example of a built-in class, like Array or Hash, which behaves differently with each and each_entry?

Alexander Popov
  • 23,073
  • 19
  • 91
  • 130

2 Answers2

13

They are different. Using the examples from RDoc:

class Foo
  include Enumerable
  def each
    yield 1
    yield 1, 2
    yield
  end
end

Foo.new.each_entry{|o| p o}
# =>
1
[1, 2]
nil

Foo.new.each{|o| p o}
# =>
1
1
nil

Foo.new.each{|*o| p o}
# =>
[1]
[1, 2]
[]

The difference is that each_entry passes all elements to the sole block variable by behaving differently depending on the number of elements passed in a single iteration: if none, it takes it as nil, if one, it takes that parameter, otherwise, it puts them in an array. each, on the other hand, passes to the sole block variable only the first object that is passed in each iteration.

sawa
  • 165,429
  • 45
  • 277
  • 381
  • Wow, thank you. One more thing, though: if `each` "only takes the first object that is passed in each iteration" how comes it gives the output in the third example, when used with the splat operator? Can we say - in order to make `each` accept not only the first element given in a single iteration - use the splat operator. – Alexander Popov Nov 07 '13 at 15:54
  • 1
    To be more precise, it passes only the first object to the first block variable. Edited the answer. – sawa Nov 07 '13 at 15:56
6

In addition to @sawa:

class Alphabet
  include Enumerable
  AZ = ('a'..'z')
  def each
    AZ.each{|char| yield char}
  end
end

p Alphabet.new.each_entry #<Enumerator: #<Alphabet:0x000000028465c8>:each_entry>
p Alphabet.new.each       #in `block in each': no block given (yield) (LocalJumpError)
steenslag
  • 79,051
  • 16
  • 138
  • 171