module Enumerable::Argumentable
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]
Public Class Methods
Helper method to wrap Enumerable methods.
# 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 %Q{ def #{m}( *args, &yld ) enum_for(:each, *args).#{m}( &yld ) end } when 1 class_eval %Q{ 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 %Q{ def #{m}( *args, &yld ) enum_for(:each).#{m}( *args, &yld ) end } end end
Public Instance Methods
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| ... }
# 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
Support for to_a.
# File lib/standard/facets/enumargs.rb, line 74 def to_a(*args) #map(*args){ |x| x } enum_for(:each, *args).to_a end