Version 0.1.0: Vollstaendig neugeschrieben. Klassen statt Lambdas. Erweiterbar

This commit is contained in:
Denis Knauf 2010-05-20 17:07:23 +02:00
parent 8e883065ca
commit 63b6ac53b1
2 changed files with 142 additions and 41 deletions

View file

@ -1 +1 @@
0.0.2 0.1.0

View file

@ -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