Module: Enumerable::Argumentable

Defined in:
lib/standard/facets/enumargs.rb

Overview

This is a simple reimplementation of the core Enumerable module to allow its 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 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. However, The methods #find and #detect have been made modified to work by removing its rarely used optional parameter and providing instead an optional keyword parameter (:ifnone => …). Please keep these difference in mind.

Example

require 'enumargs'

class T
  include Enumerable::Argumentable
  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

Helper method to wrap Enumerable methods.


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/standard/facets/enumargs.rb', line 34

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
    # this branch is used when the method has a variable number of arguments
    #   resulting in an arity of -1.  Right now this is bugged as it does
    #   not pass the argument to the each, and always passes the argument
    #   to the method.  This makes methods like .min amdn .max to act
    #   in an unexpected manner.
    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| ... }

85
86
87
88
89
90
91
92
93
# File 'lib/standard/facets/enumargs.rb', line 85

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

#to_a(*args) ⇒ Object

Support for #to_a.


74
75
76
77
# File 'lib/standard/facets/enumargs.rb', line 74

def to_a(*args)
  #map(*args){ |x| x }
  enum_for(:each, *args).to_a
end