## # Enumerable # # The Enumerable mixin provides collection classes with # several traversal and searching methods, and with the ability to # sort. The class must provide a method `each`, which # yields successive members of the collection. If # {Enumerable#max}, {#min}, or # {#sort} is used, the objects in the collection must also # implement a meaningful `<=>` operator, as these methods # rely on an ordering between members of the collection. # # @ISO 15.3.2 module Enumerable NONE = Object.new ## # Call the given block for each element # which is yield by +each+. Return false # if one block value is false. Otherwise # return true. If no block is given and # +self+ is false return false. # # ISO 15.3.2.2.1 def all?(&block) if block self.each{|*val| return false unless block.call(*val)} else self.each{|*val| return false unless val.__svalue} end true end ## # Call the given block for each element # which is yield by +each+. Return true # if one block value is true. Otherwise # return false. If no block is given and # +self+ is true object return true. # # ISO 15.3.2.2.2 def any?(&block) if block self.each{|*val| return true if block.call(*val)} else self.each{|*val| return true if val.__svalue} end false end ## # Call the given block for each element # which is yield by +each+. Append all # values of each block together and # return this value. # # ISO 15.3.2.2.3 def collect(&block) return to_enum :collect unless block ary = [] self.each{|*val| ary.push(block.call(*val))} ary end ## # Return the first element for which # value from the block is true. If no # object matches, calls +ifnone+ and # returns its result. Otherwise returns # +nil+. # # ISO 15.3.2.2.4 def detect(ifnone=nil, &block) return to_enum :detect, ifnone unless block self.each{|*val| if block.call(*val) return val.__svalue end } ifnone.call unless ifnone.nil? end ## # Call the given block for each element # which is yield by +each+. Pass an # index to the block which starts at 0 # and increase by 1 for each element. # # ISO 15.3.2.2.5 def each_with_index(&block) return to_enum :each_with_index unless block i = 0 self.each{|*val| block.call(val.__svalue, i) i += 1 } self end ## # Return an array of all elements which # are yield by +each+. # # ISO 15.3.2.2.6 def entries ary = [] self.each{|*val| # __svalue is an internal method ary.push val.__svalue } ary end ## # Alias for find # # ISO 15.3.2.2.7 alias find detect ## # Call the given block for each element # which is yield by +each+. Return an array # which contains all elements whose block # value was true. # # ISO 15.3.2.2.8 def find_all(&block) return to_enum :find_all unless block ary = [] self.each{|*val| ary.push(val.__svalue) if block.call(*val) } ary end ## # Call the given block for each element # which is yield by +each+ and which return # value was true when invoking === with # +pattern+. Return an array with all # elements or the respective block values. # # ISO 15.3.2.2.9 def grep(pattern, &block) ary = [] self.each{|*val| sv = val.__svalue if pattern === sv ary.push((block)? block.call(*val): sv) end } ary end ## # Return true if at least one element which # is yield by +each+ returns a true value # by invoking == with +obj+. Otherwise return # false. # # ISO 15.3.2.2.10 def include?(obj) self.each{|*val| return true if val.__svalue == obj } false end ## # Call the given block for each element # which is yield by +each+. Return value # is the sum of all block values. Pass # to each block the current sum and the # current element. # # ISO 15.3.2.2.11 def inject(*args, &block) raise ArgumentError, "too many arguments" if args.size > 2 if Symbol === args[-1] sym = args[-1] block = ->(x,y){x.__send__(sym,y)} args.pop end if args.empty? flag = true # no initial argument result = nil else flag = false result = args[0] end self.each{|*val| val = val.__svalue if flag # push first element as initial flag = false result = val else result = block.call(result, val) end } result end alias reduce inject ## # Alias for collect # # ISO 15.3.2.2.12 alias map collect ## # Return the maximum value of all elements # yield by +each+. If no block is given <=> # will be invoked to define this value. If # a block is given it will be used instead. # # ISO 15.3.2.2.13 def max(&block) flag = true # 1st element? result = nil self.each{|*val| val = val.__svalue if flag # 1st element result = val flag = false else if block result = val if block.call(val, result) > 0 else result = val if (val <=> result) > 0 end end } result end ## # Return the minimum value of all elements # yield by +each+. If no block is given <=> # will be invoked to define this value. If # a block is given it will be used instead. # # ISO 15.3.2.2.14 def min(&block) flag = true # 1st element? result = nil self.each{|*val| val = val.__svalue if flag # 1st element result = val flag = false else if block result = val if block.call(val, result) < 0 else result = val if (val <=> result) < 0 end end } result end ## # Alias for include? # # ISO 15.3.2.2.15 alias member? include? ## # Call the given block for each element # which is yield by +each+. Return an # array which contains two arrays. The # first array contains all elements # whose block value was true. The second # array contains all elements whose # block value was false. # # ISO 15.3.2.2.16 def partition(&block) return to_enum :partition unless block ary_T = [] ary_F = [] self.each{|*val| if block.call(*val) ary_T.push(val.__svalue) else ary_F.push(val.__svalue) end } [ary_T, ary_F] end ## # Call the given block for each element # which is yield by +each+. Return an # array which contains only the elements # whose block value was false. # # ISO 15.3.2.2.17 def reject(&block) return to_enum :reject unless block ary = [] self.each{|*val| ary.push(val.__svalue) unless block.call(*val) } ary end ## # Alias for find_all. # # ISO 15.3.2.2.18 alias select find_all ## # Return a sorted array of all elements # which are yield by +each+. If no block # is given <=> will be invoked on each # element to define the order. Otherwise # the given block will be used for # sorting. # # ISO 15.3.2.2.19 def sort(&block) self.map{|*val| val.__svalue}.sort(&block) end ## # Alias for entries. # # ISO 15.3.2.2.20 alias to_a entries # redefine #hash 15.3.1.3.15 def hash h = 12347 i = 0 self.each do |e| h = __update_hash(h, i, e.hash) i += 1 end h end end