How to implement an enumerator in Ruby?
Asked Answered
A

2

6

For example:

a = [1,2,3,4,5]
a.delete_if { |x| x > 3 }

is equivalent to:

a = [1,2,3,4,5]
a.delete_if.each.each.each.each { |x| x > 3 }

I know a.delete_if returns an enumerator. But how does it know it should delete object when the each block returns true? How to implement delete_if by hand(and in Ruby)?

Albanian answered 7/10, 2011 at 19:34 Comment(2)
[1,2,3,4,5].delete_if.each.each.each.each { |x| x > 3 } Could you please elaborate a bit more on this line?Egin
why isn't delete_if.each the same as each? how does delete_if remember what should it do?Albanian
A
4

You can take a look at the Rubinius source code: enumerable module

Here an example of the reject method:

  def reject
    return to_enum(:reject) unless block_given?

    ary = []
    each do |o|
      ary << o unless yield(o)
    end

    ary
  end
Aftergrowth answered 7/10, 2011 at 19:56 Comment(0)
P
1

In the implementation of delete_if, the code can verify the value returned from yield to decide whether or not to delete the given entry from the array.

You can read Implementing Iterators in the Programming Ruby guide for more details, but it would looks something like:

class Array
  def delete_if
     reject { |i| yield i }.to_a
  end
end

The above uses yield to pass each item in the array to the block associated with the call to delete_if, and implicitly returns the value of the yield to the outer reject call.

Pallaton answered 7/10, 2011 at 19:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.