Module: EnumerablePass

Included in:
Interval
Defined in:
lib/more/facets/enumerablepass.rb

Overview

EnumerablePass

This is a simple reimplementation of the core Enumerable module to allow the methods to take and pass-on arbitrary arguments to the underlying #each call. This library uses Enumerator and scans Enumerable so it can alwasy stay in sync.

NOTE Any Enumerable method with a negative arity cannot do pass arguments due to ambiguity in the argument count. So the methods #inject and #zip do NOT work this way, but simply work as they do in Enumerable. The method #find (and #detect) though has been made to work by removing its rarely used optional parameter and providing instead an optional keyword parameter (:ifnone => …). Please keep these difference in mind.

Synopsis

class T
  include EnumerablePass
  def initialize(arr)
    @arr = arr
  end
  def each(n)
    arr.each{ |e| yield(e+n) }
  end
end

t = T.new([1,2,3])
t.collect(4)
#=> [5,6,7]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.wrap_enumerable_method(methodname) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/more/facets/enumerablepass.rb', line 65

def self.wrap_enumerable_method( methodname )

  m = methodname
  meth = Enumerable.instance_method(m)
  arity = meth.arity

  case arity <=> 0
  when 0
    class_eval %{
      def #{m}( *args, &yld )
        enum_for(:each, *args).#{m}( &yld )
      end
    }
  when 1
    class_eval %{
      def #{m}( *args, &yld )
        args, each_args = args[0...#{arity}], args[#{arity}..-1]
        enum_for(:each, *each_args).#{m}( *args, &yld )
      end
    }
  else
    class_eval %{
      def #{m}( *args, &yld )
        enum_for(:each).#{m}( *args, &yld )
      end
    }
  end
end

Instance Method Details

#find(*args, &yld) ⇒ Object Also known as: detect

Make exception for #find (a negative arity method) to accept keyword argument.

ObjectSpace.find(Class, :ifnone=>lambda{1}) { |e| ... }
ObjectSpace.find(Class, :ifnone=>lambda{1}) { |e| ... }


104
105
106
107
108
109
110
111
112
# File 'lib/more/facets/enumerablepass.rb', line 104

def find(*args, &yld)  # future use **keys ?
  if Hash === args.last and args.last.key?(:ifnone)
    ifnone = args.last.delete(:ifnone)
    args.pop if args.last.empty?
    enum_for(:each, *args).find( ifnone, &yld )
  else
    enum_for(:each, *args).find( &yld )
  end
end