This repository has been archived on 2021-12-03. You can view files and clone it, but cannot push or open issues/pull-requests.
functional/lib/functional.rb

270 lines
3.4 KiB
Ruby
Raw Normal View History

2010-04-19 20:22:54 +02:00
class ::Regexp
class NegRegexp
def initialize r
@rx = r
end
def match l
! @rx.match( l)
end
def =~ l
! @rx =~ l
end
def -@
@rx
end
2010-05-20 14:48:42 +02:00
end
2010-05-20 14:48:42 +02:00
def -@
NegRegexp.new self
2010-05-20 14:48:42 +02:00
end
end
class ::Object
def functional meth = nil
Functional.new self, meth
2010-05-20 14:48:42 +02:00
end
2010-05-25 19:02:49 +02:00
alias to_fun functional
2010-05-20 14:48:42 +02:00
end
2010-04-19 20:22:54 +02:00
class Functional
include Enumerable
class Base
attr_reader :exe
attr_accessor :next
def initialize &e
@exe = e
end
def call *a
@next.call *a
end
def end
@next.end
end
def to_proc
method( :call).to_proc
end
2010-04-19 20:22:54 +02:00
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
2010-04-19 20:22:54 +02:00
end
class To_a <Inject
def initialize *a, &e
super [], *a, &e
end
end
class Map <Collect
def call *a
2010-05-25 19:02:49 +02:00
@exe.call *a, &@next
end
end
class Reduce <Base
2010-05-25 19:02:49 +02:00
def initialize iv, *a, &e
super *a, &e
@buf = {}
@buf.default = iv
end
def call *a
2010-05-25 19:02:49 +02:00
@buf[ a[0]] = @exe.call @buf[ a[0]], *a[1..-1]
end
def end
@buf.each {|i| @next.call *i}
@next.end
end
end
attr_accessor :next, :stack, :obj, :func, :args
2010-04-19 20:22:54 +02:00
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
2010-04-19 20:22:54 +02:00
end
def collect &exe
push Collect.new( &exe)
2010-04-19 20:22:54 +02:00
end
2010-05-25 19:02:49 +02:00
def map &exe
push Map.new( &exe)
end
2010-05-25 19:02:49 +02:00
def reduce iv, &exe
push Reduce.new( iv, &exe)
2010-04-19 20:22:54 +02:00
end
2010-04-19 21:08:49 +02:00
2010-04-19 20:22:54 +02:00
def select &exe
push Select.new( &exe)
2010-04-19 20:22:54 +02:00
end
def grep re
push Select.new( &re.method( :match))
2010-05-20 14:48:42 +02:00
end
2010-04-19 20:22:54 +02:00
def delete_if &exe
push DeleteIf.new( &exe)
2010-04-20 16:50:59 +02:00
end
def compact
push Compact.new
end
def updown init, &exe
push UpDown.new( init, &exe)
2010-04-20 16:50:59 +02:00
end
def topdown init, &exe
push TopDown.new( init, &exe)
2010-04-19 20:22:54 +02:00
end
def each &exe
return self unless exe
push Each.new
push exe
run
end
def join deli
push Inject.new('') {|i,j|i+deli+j}
run
end
def run
@obj.send @func||:each, *@args, &@next #.method(:call)
@next.end
2010-04-19 20:22:54 +02:00
end
2010-04-20 18:54:35 +02:00
def p
2010-05-25 19:02:49 +02:00
each {|*a|Kernel.p a}
2010-04-20 18:54:35 +02:00
end
2010-04-19 20:22:54 +02:00
end
begin
require 'tokyocabinet'
class Functional
class Map <Base
class Emit < TokyoCabinet::BDB
alias emit putdup
alias call emit
end
def call *a
@exe.call( *a).each &@next
end
end
def map name, &e
push Map.new( name, &e)
end
def Reduce name, &e
push Reduce.new( name, &e)
end
end
rescue MissingSourceFile
# TokyoCabinet not installed?
end if false