# = Elementor # # Provides elementwise functionality. # # == Authors # # * Thomas Sawyer # * George Moschovitis # * Martin DeMello # # == Notes # # * This could have been impemented with a generic Functor, rather than # the specialized Elementor, but for the fact Procs can not yet # handle blocks. # * There used to be a "Cascading Elementor", but that proved idiotic # in the face of adding an instance_eval block to #every. # * Any ideas for a better name for #accumulate? --gmosx # * The use of every! and it's relation to Enumerator still seems a bit # off beat. Should #every always use #map? And another method #each? # # == Copying # # Copyright (c) 2006 Thomas Sawyer # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. require 'enumerator' require 'facets/functor' module Enumerable # Create Elementor. def to_elem(meth=nil) Elementor.new(self, meth || :map) end def per @__per__ ||= Functor.new do |op| Elementor.new(self, op) end end # Returns an elemental object. This allows # you to map a method on to every element. # # r = [1,2,3].every + 3 #=> [4,5,6] def every @_every ||= to_elem end # In place version of #every. def every! raise NoMethodError unless respond_to?(:map!) @_every_inplace ||= to_elem(:map!) end #def every # @_every ||= Functor.new do |op,*args| # map{ |a| a.send(op,*args) } # end #end #def every! # raise NoMethodError unless respond_to?(:map!) # @_every_inplace ||= Functor.new do |op,*args| # map!{ |a| a.send(op,*args) } # end #end # Possible name change for every. # # r = [1,2,3].elements + 3 #=> [4,5,6] # # Certainly reads better. alias_method :elements, :every alias_method :elements!, :every! end # = Elementor # # Elementor is a type of Functor. Operations # applied to it are routed to each element. class Enumerable::Elementor private(*instance_methods.select{|x| x !~ /^__/ }) def initialize(elem_object, elem_method=nil) @elem_object = elem_object @elem_method = elem_method || :map end def instance_delegate @elem_object end def instance_operator @elem_method end def method_missing(sym,*args,&blk) @elem_object.__send__(@elem_method){ |x| x.__send__(sym,*args,&blk) } end end class Enumerable::Enumerator # Create Elementor. def to_elem(meth=nil) Elementor.new(self, meth || :each) end # Enumerator doesn't support inplace element operations, per se. undef_method :every! undef_method :elements! end