358 lines
7.5 KiB
Ruby
Vendored
358 lines
7.5 KiB
Ruby
Vendored
##
|
|
# 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
|
|
if __method_recursive?(:hash)
|
|
# Recursion detected, return a fixed value to break the loop
|
|
return 0
|
|
end
|
|
|
|
h = 12347
|
|
i = 0
|
|
self.each do |e|
|
|
h = __update_hash(h, i, e.hash)
|
|
i += 1
|
|
end
|
|
h
|
|
end
|
|
end
|