diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8146014
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+functional.gemspec
+pkg
diff --git a/README.md b/README.md
index d625a86..1478272 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+Obsolete
+========
+
+Use `#lazy`.
+
Install
=======
@@ -8,8 +13,88 @@ Usage
require 'functional'
- obj = 0 .. 10**12
- Functional.new( obj).select {|i| i.even? }.collect {|i| i/3 }.select {|i| i.even? }.each &method( :puts)
+ # To demonstrate Functional, we create a Class with a infinite loop:
+ class Sequence
+ include Enumerable
+ def initialize first = 0, step = 1
+ @i, @step = first, step
+ end
+ def each
+ # Our infinite loop:
+ loop do
+ yield @i
+ @i += @step
+ end
+ end
+ end
+
+ Functional.new( Sequence.new).
+ select {|i| i.even? }.
+ collect {|i| i/3 }.
+ select {|i| i.even?}.
+ collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
+ flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
+ p
+
+ # Without Functional... Bye bye.
+ Sequence.new.
+ select {|i| i.even? }.
+ collect {|i| i/3 }.
+ select {|i| i.even?}.
+ collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
+ flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
+ p
+
+It will never realize, that #p doesn't exists, because the first select runs endless.
+Functional#p prints everything to stdout.
+
+ (0..100000).to_fun.
+ collect {|i| i*3 }.
+ select {|i| i%5 == 2 }.
+ to_a
+
+Thanks to `Symbol#to_proc`:
+
+ Sequence.new.to_fun.
+ select( &:even?).
+ collect {|i| i/3 }.
+ select( &:even?).
+ collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
+ flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
+ p
+
+If you know methodphitamine, combine it:
+
+ require 'methodphitamine'
+
+ Sequence.new.to_fun.
+ select( &it.even?).
+ collect( &it/3).
+ select( &it.even?).
+ collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
+ flatten.
+ p
+
+ (0..100000).to_fun.
+ collect( &it*3).
+ select( &it%5 == 2).
+ to_a
+
+Makros
+======
+
+ seq = Sequence.new.to_fun
+ seq = seq.select &it.even? if must_be_even
+ seq = seq.
+ collect( &it/3).
+ select( &it.even?).
+ collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }
+ seq = seq.flatten if please_flatten
+ if print_it
+ seq.p
+ else
+ seq_to_a
+ end
What's with _#map_?
=================
diff --git a/VERSION b/VERSION
index 8acdd82..9faa1b7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.0.1
+0.1.5
diff --git a/lib/functional.rb b/lib/functional.rb
index dce2126..f129e3d 100644
--- a/lib/functional.rb
+++ b/lib/functional.rb
@@ -1,46 +1,465 @@
-
-class Functional
- include Enumerable
-
- def self.method_missing meth, *args, &exe
- self.new.send meth, *args, &exe
+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
end
- def push_method code, *args, &exe
- name = "__meth_#{exe.object_id}"
- define_singleton_method name, &exe
- @stack.push [code % name]+args
+ def -@
+ NegRegexp.new self
+ end
+end
+
+class ::Object
+ def to_fun meth = nil
+ Functional.new self, meth
+ end
+end
+
+class Counter
+ include Enumerable
+ attr_reader :c
+
+ def initialize first = nil, step = nil
+ @c, @step = first || 0, step || 1
+ end
+
+ def next; @c += @step end
+ def to_i; c.to_i end
+ def to_f; c.to_f end
+
+ def + i
+ @c += @step*i
+ end
+
+ def each &e
+ loop { e.call self; self.next }
+ end
+end
+
+class Functional
+ def self.__version__() '0.1.5' end
+ include Enumerable
+
+ class DEFAULT
+ end
+
+ class Base
+ attr_reader :exe
+ attr_accessor :next
+ attr_reader :caller
+
+ def initialize &e
+ @caller = Kernel.caller.first
+ @exe = e
+ end
+
+ def base_fun *a
+ @next.call *a
+ end
+ alias call base_fun
+
+ def end
+ @next.end
+ end
+
+ def clean
+ @next.clean
+ end
+
+ def to_proc
+ method( :call).to_proc
+ end
+ end
+
+ class Collect @buf.size
+ @next.call @buf
+ @buf.clear
+ end
+ end
+ alias call slice_fun
+
+ def end
+ @next.call @buf
+ @next.end
+ end
+ end
+
+ class Cons @buf.size
+ class < @buf.size
+ @next.end
+ end
+ end
+
+ class Pager [ [0, _A], [1, _B], ..., [_I, _C], ..., [_N, _D]]
+ # [ [_A|_As], [_B|_Bs], ..., [_C|_Cs], ..., [_D|_Ds] ] ==> [ [0,_A|_As], [1,_B|_Bs], ..., [_I,_C|_Cs], ..., [_N,_D|_Ds] ]
+ def with_index &exe
+ i = 0
+ exe ||= Array.method :[]
+ push Collect.new {|*a| exe.call i, *a; i += 1 }
+ end
+
+ def slice n, &exe
+ push Slice.new( n)
+ block_given? ? self.collect( &exe) : self
+ end
+
+ def cons n, &exe
+ push Cons.new( n)
+ block_given? ? self.collect( &exe) : self
+ end
+
+ def tap &exe
+ push Tap.new( &exe)
+ end
+
+ class Save < Base
+ attr_reader :db
+
+ def initialize db
+ @db = db
+ end
+
+ def call k, *v
+ @db[ k] = v.length == 1 ? v.first : v
+ end
+ end
+
+ def save db
+ push Save.new( db)
end
end
diff --git a/test/functional_test.rb b/test/functional_test.rb
new file mode 100644
index 0000000..9497c66
--- /dev/null
+++ b/test/functional_test.rb
@@ -0,0 +1,29 @@
+require 'test/unit'
+require 'functional'
+
+class FunTest < Test::Unit::TestCase
+ M = 0..100
+
+ def doit_fun m, &exe
+ f = m.to_fun
+ yield f
+ f.to_a
+ end
+
+ def test_to_fun_exists
+ assert_respond_to Object, :to_fun
+ end
+
+ def test_to_a
+ assert_equal M.to_a, doit_fun( M) {|x| x }
+ end
+
+ def test_collect
+ l = lambda {|x| x*2}
+ assert_equal M.collect( &l), doit_fun( M) {|x| x.collect( &l) }
+ end
+
+ def test_inject
+ assert_equal M.inject( 0) {|i,j| i+j }, M.to_fun.inject( 0) {|i,j| i+j }
+ end
+end