module IdempotentEnumerable

Public Class Methods

included(klass) click to toggle source
# File lib/idempotent_enumerable.rb, line 4
def self.included(klass)
  def klass.idempotent_enumerable
    @idempotent_enumerable ||= Configurator.new(self)
  end
end

Public Instance Methods

chunk(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 19
def chunk(*arg, &block)
  # FIXME: should return enumerator
  return to_enum(:chunk, *arg) unless block
  each(*arg).chunk(&block).map { |key, group| [key, idempotently_construct(group)] }
end
chunk_while(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 26
def chunk_while(*arg, &block)
  idempotent_enumerator(each(*arg).chunk_while(&block))
end
drop(num, *arg) click to toggle source
# File lib/idempotent_enumerable.rb, line 31
def drop(num, *arg)
  idempotently_construct(each(*arg).drop(num))
end
each_cons(num, *arg) { |idempotently_construct(slice)| ... } click to toggle source
# File lib/idempotent_enumerable.rb, line 35
def each_cons(num, *arg)
  return to_enum(:each_cons, num, *arg) unless block_given?
  each(*arg).each_cons(num) { |slice| yield(idempotently_construct(slice)) }
end
each_slice(num, *arg) { |idempotently_construct(slice)| ... } click to toggle source
# File lib/idempotent_enumerable.rb, line 40
def each_slice(num, *arg)
  return to_enum(:each_slice, num, *arg) unless block_given?
  each(*arg).each_slice(num) { |slice| yield(idempotently_construct(slice)) }
end
first(*arg) click to toggle source
# File lib/idempotent_enumerable.rb, line 45
def first(*arg)
  arg, num = idempotent_split_arg(arg)
  num ? idempotently_construct(each(*arg).first(*num)) : each(*arg).first
end
grep(*arg, pattern, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 50
def grep(*arg, pattern, &block)
  idempotently_construct(each(*arg).grep(pattern, &block))
end
grep_v(pattern, *arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 55
def grep_v(pattern, *arg, &block)
  idempotently_construct(each(*arg).grep_v(pattern, &block))
end
group_by(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 60
def group_by(*arg, &block)
  each(*arg).group_by(&block).map { |key, val| [key, idempotently_construct(val)] }.to_h
end
max(*arg) click to toggle source
# File lib/idempotent_enumerable.rb, line 75
def max(*arg)
  arg, num = idempotent_split_arg(arg)
  num ? idempotently_construct(each(*arg).max(*num)) : each(*arg).max
end
max_by(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 80
def max_by(*arg, &block)
  return to_enum(:max_by, *arg) unless block
  arg, num = idempotent_split_arg(arg)
  num ? idempotently_construct(each(*arg).max_by(*num, &block)) : each(*arg).max_by(&block)
end
min(*arg) click to toggle source
# File lib/idempotent_enumerable.rb, line 64
def min(*arg)
  arg, num = idempotent_split_arg(arg)
  num ? idempotently_construct(each(*arg).min(*num)) : each(*arg).min
end
min_by(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 69
def min_by(*arg, &block)
  return to_enum(:min_by, *arg) unless block
  arg, num = idempotent_split_arg(arg)
  num ? idempotently_construct(each(*arg).min_by(*num, &block)) : each(*arg).min_by(&block)
end
partition(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 86
def partition(*arg, &block)
  return to_enum(:partition, *arg) unless block
  each(*arg).partition(&block).map(&method(:idempotently_construct))
end
slice_after(pattern = nil, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 96
def slice_after(pattern = nil, &block)
  idempotent_enumerator(pattern ? each.slice_after(pattern) : each.slice_after(&block))
end
slice_before(pattern = nil, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 91
def slice_before(pattern = nil, &block)
  idempotent_enumerator(pattern ? each.slice_before(pattern) : each.slice_before(&block))
end
slice_when(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 100
def slice_when(*arg, &block)
  idempotent_enumerator(each(*arg).slice_when(&block))
end
sort(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 105
def sort(*arg, &block)
  idempotently_construct(each(*arg).sort(&block))
end
take(num, *arg) click to toggle source
# File lib/idempotent_enumerable.rb, line 109
def take(num, *arg)
  idempotently_construct(each(*arg).take(num))
end
uniq(*arg, &block) click to toggle source
# File lib/idempotent_enumerable.rb, line 114
def uniq(*arg, &block)
  idempotently_construct(each(*arg).uniq(&block))
end

Private Instance Methods

idempotent_enumerator(enumerator) click to toggle source
# File lib/idempotent_enumerable.rb, line 125
def idempotent_enumerator(enumerator)
  Enumerator.new { |y| enumerator.each { |chunk| y << idempotently_construct(chunk) } }
end
idempotent_split_arg(arg) click to toggle source

For methods like min(), with optional argument (count of min elements), AND complex collections that have args for their each method, we need to split args to “args to each” and “args to min”.

Doesn't work if each has variable number of args, unfortunately.

# File lib/idempotent_enumerable.rb, line 135
def idempotent_split_arg(arg)
  arity = method(:each).arity
  return [arg] if arity < 0 || arg.count <= arity
  [arg[0...arity], arg[arity..-1]]
end
idempotently_construct(array) click to toggle source
# File lib/idempotent_enumerable.rb, line 121
def idempotently_construct(array)
  self.class.send(self.class.idempotent_enumerable.constructor, array)
end