It's possible to implement an each method in a class mixing in
Enumerable that runs forever, and thus causing, for example, to_a to run
forever.  One such class is mathn's Prime class:

require 'mathn'
Prime.new.to_a # <- runs forever, never returns

This seems a bit broken to me, and I was writing a program where I
needed the first n primes, or all the primes under 200, for example, so
I re-wrote Enumerable#to_a like so to make my code more idiomatic:

----8<----
module Enumerable
  def to_a(n = nil)
    result = []
    inclusion_condition = true
    return result if n.to_i <= 0 and !block_given?
    each do |*elements|
      elements = elements.first if elements.size == 1
      if block_given?
        values = result.last
        inclusion_condition = yield(*values) unless values.nil?
      else
        inclusion_condition = n != result.size
      end

      if inclusion_condition
        result << elements
      else
        result.pop if block_given?
        break result
      end
    end
    result
  end
end
----8<----

This allows, for example, the following:
Prime.new.to_a(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] , the first
10 primes
Prime.new.to_a {|prime| prime < 20} # => [2, 3, 5, 7, 11, 13, 17, 19] ,
all the primes under 20

Passed an integer paramater, the code will return an array that long, or
until the Enumerable runs out.  Passed a block, it will return an array
of elements, adding elements until the block evaluates to false.

This code surely could use some hacking, refactoring, and possibly bug
fixing.  I've made a post[1] on http://refactormycode.com just for that
purpose.

Thoughts?

[1]
http://refactormycode.com/codes/196-enumerable-to_a-with-terminating-conditions

-Ben Kudria
--
http://ben.kudria.net | Jabber: ben / kudria.net
-- 
Posted via http://www.ruby-forum.com/.