Version 0.1.0: Vollstaendig neugeschrieben. Klassen statt Lambdas. Erweiterbar
This commit is contained in:
parent
8e883065ca
commit
63b6ac53b1
|
@ -23,26 +23,138 @@ end
|
||||||
class Functional
|
class Functional
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
def self.method_missing meth, *args, &exe
|
class Base
|
||||||
self.new.send meth, *args, &exe
|
attr_reader :exe
|
||||||
|
attr_accessor :next
|
||||||
|
def initialize &e
|
||||||
|
@exe = e
|
||||||
end
|
end
|
||||||
|
|
||||||
def push_method meth, *args, &exe
|
def call *a
|
||||||
@stack.push [meth, exe]+args
|
@next.call *a
|
||||||
|
end
|
||||||
|
|
||||||
|
def end
|
||||||
|
@next.end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Collect <Base
|
||||||
|
def call *a
|
||||||
|
@next.call *@exe.call( *a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Select <Base
|
||||||
|
def call *a
|
||||||
|
@next.call *a if @exe.call *a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DeleteIf <Base
|
||||||
|
def call *a
|
||||||
|
@next.call *a unless @exe.call *a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Compact <Base
|
||||||
|
def call *a
|
||||||
|
@next.call *a unless a.empty? || [nil] == a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class BottomUp <Base
|
||||||
|
def initialize start, *a, &e
|
||||||
|
@next.call *a, &e
|
||||||
|
@buffer, @start = nil, start
|
||||||
|
end
|
||||||
|
|
||||||
|
def call a
|
||||||
|
if @exe.call a
|
||||||
|
@next.call @buffer+a
|
||||||
|
@buffer = @start.dup
|
||||||
|
else
|
||||||
|
@buffer += a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def end
|
||||||
|
@next.call @buffer
|
||||||
|
@next.end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class TopDown <Base
|
||||||
|
def initialize start, *a, &e
|
||||||
|
@next.call *a, &e
|
||||||
|
@buffer, @start = nil, start
|
||||||
|
end
|
||||||
|
|
||||||
|
def call a
|
||||||
|
if @exe.call a
|
||||||
|
@next.call @buffer
|
||||||
|
@buffer = @start.dup+a
|
||||||
|
else
|
||||||
|
@buffer += a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def end
|
||||||
|
@next.call @buffer
|
||||||
|
@next.end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Each <Base
|
||||||
|
def end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class P <Each
|
||||||
|
def initialize *a
|
||||||
|
super *a, &Kernel.method( :p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Inject <Base
|
||||||
|
attr_reader :it
|
||||||
|
def initialize start, *a, &e
|
||||||
|
super *a, &e
|
||||||
|
@it = start
|
||||||
|
end
|
||||||
|
def call *a
|
||||||
|
@it = @exe.call @it, *a
|
||||||
|
end
|
||||||
|
def end
|
||||||
|
@it
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class To_a <Inject
|
||||||
|
def initialize *a, &e
|
||||||
|
super [], *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :next, :stack, :obj, :func, :args
|
||||||
|
|
||||||
|
def initialize obj = nil, func = nil, *args
|
||||||
|
@next, @stack, @obj, @func, @args = self, self, obj, func, args
|
||||||
|
end
|
||||||
|
|
||||||
|
def push a
|
||||||
|
@stack = @stack.next = a
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize obj = nil, func = nil, *args
|
|
||||||
@stack, @obj, @func, @args = [], obj, func, args
|
|
||||||
end
|
|
||||||
|
|
||||||
def collect &exe
|
def collect &exe
|
||||||
push_method :collect, &exe
|
push Collect.new( &exe)
|
||||||
end
|
end
|
||||||
|
|
||||||
# map/reduce?
|
# map/reduce?
|
||||||
def map &exe
|
def map &exe
|
||||||
push_method :map, &exe
|
push Map.new( &exe)
|
||||||
end
|
end
|
||||||
|
|
||||||
# map/reduce?
|
# map/reduce?
|
||||||
|
@ -51,49 +163,38 @@ class Functional
|
||||||
end
|
end
|
||||||
|
|
||||||
def select &exe
|
def select &exe
|
||||||
push_method :select, &exe
|
push Select.new( &exe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def grep r
|
def grep re
|
||||||
push_method :select, &r.method( :match)
|
push Select.new( &re.method( :match))
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_if &exe
|
def delete_if &exe
|
||||||
push_method :delete_if, &exe
|
push DeleteIf.new( &exe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def compact
|
def compact
|
||||||
push_method :compact
|
push Compact.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def together init, &exe
|
def updown init, &exe
|
||||||
push_method :together, init, &exe
|
push UpDown.new( init, &exe)
|
||||||
|
end
|
||||||
|
|
||||||
|
def topdown init, &exe
|
||||||
|
push TopDown.new( init, &exe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def each &exe
|
def each &exe
|
||||||
return self unless exe
|
push Each.new
|
||||||
callstack = exe
|
push exe
|
||||||
@stack.reverse.each do |a|
|
run
|
||||||
m, e = *a[0..1]
|
|
||||||
pre = callstack
|
|
||||||
callstack = case m
|
|
||||||
when :collect then lambda {|val| pre.call e.call( val) }
|
|
||||||
when :select then lambda {|val| pre.call val if e.call val }
|
|
||||||
when :delete_if then lambda {|val| pre.call val unless e.call val }
|
|
||||||
when :compact then lambda {|val| pre.call val if val }
|
|
||||||
when :map then lambda {|val| e.call( val).each &pre }
|
|
||||||
when :reduce
|
|
||||||
buf = {}
|
|
||||||
lambda {|val| buf[ val.first] = e.call( *val) }
|
|
||||||
when :together
|
|
||||||
buf = a[2].dup
|
|
||||||
lambda {|val| if e.call val then pre.call buf; buf = a[2].dup+val else buf += val end }
|
|
||||||
else
|
|
||||||
$stderr.puts "Whats that? #{m.inspect}"
|
|
||||||
callstack
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
@obj.send @func||:each, *@args, &callstack
|
def run
|
||||||
|
@obj.send @func||:each, *@args, &@next.method(:call)
|
||||||
|
@next.end
|
||||||
end
|
end
|
||||||
|
|
||||||
def p
|
def p
|
||||||
|
|
Reference in a new issue