functional 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +82 -2
- data/VERSION +1 -1
- data/lib/functional.rb +211 -45
- metadata +8 -6
data/README.md
CHANGED
@@ -8,8 +8,88 @@ Usage
|
|
8
8
|
|
9
9
|
require 'functional'
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# To demonstrate Functional, we create a Class with a infinite loop:
|
12
|
+
class Sequence
|
13
|
+
include Enumerable
|
14
|
+
def initialize first = 0, step = 1
|
15
|
+
@i, @step = first, step
|
16
|
+
end
|
17
|
+
def each
|
18
|
+
# Our infinite loop:
|
19
|
+
loop do
|
20
|
+
yield @i
|
21
|
+
@i += @step
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Functional.new( Sequence.new).
|
27
|
+
select {|i| i.even? }.
|
28
|
+
collect {|i| i/3 }.
|
29
|
+
select {|i| i.even?}.
|
30
|
+
collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
|
31
|
+
flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
|
32
|
+
p
|
33
|
+
|
34
|
+
# Without Functional... Bye bye.
|
35
|
+
Sequence.new.
|
36
|
+
select {|i| i.even? }.
|
37
|
+
collect {|i| i/3 }.
|
38
|
+
select {|i| i.even?}.
|
39
|
+
collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
|
40
|
+
flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
|
41
|
+
p
|
42
|
+
|
43
|
+
It will never realize, that #p doesn't exists, because the first select runs endless.
|
44
|
+
Functional#p prints everything to stdout.
|
45
|
+
|
46
|
+
(0..100000).to_fun.
|
47
|
+
collect {|i| i*3 }.
|
48
|
+
select {|i| i%5 == 2 }.
|
49
|
+
to_a
|
50
|
+
|
51
|
+
Thanks to `Symbol#to_proc`:
|
52
|
+
|
53
|
+
Sequence.new.to_fun.
|
54
|
+
select( &:even?).
|
55
|
+
collect {|i| i/3 }.
|
56
|
+
select( &:even?).
|
57
|
+
collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
|
58
|
+
flatten. # It flattens everything! Not like: collect {|i| i.flatten }.
|
59
|
+
p
|
60
|
+
|
61
|
+
If you know methodphitamine, combine it:
|
62
|
+
|
63
|
+
require 'methodphitamine'
|
64
|
+
|
65
|
+
Sequence.new.to_fun.
|
66
|
+
select( &it.even?).
|
67
|
+
collect( &it/3).
|
68
|
+
select( &it.even?).
|
69
|
+
collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }.
|
70
|
+
flatten.
|
71
|
+
p
|
72
|
+
|
73
|
+
(0..100000).to_fun.
|
74
|
+
collect( &it*3).
|
75
|
+
select( &it%5 == 2).
|
76
|
+
to_a
|
77
|
+
|
78
|
+
Makros
|
79
|
+
======
|
80
|
+
|
81
|
+
seq = Sequence.new.to_fun
|
82
|
+
seq = seq.select &it.even? if must_be_even
|
83
|
+
seq = seq.
|
84
|
+
collect( &it/3).
|
85
|
+
select( &it.even?).
|
86
|
+
collect {|i| [[[[[[i.even?, i.odd?]]], i, [[[[[[i.class]]]]]]]]] }
|
87
|
+
seq = seq.flatten if please_flatten
|
88
|
+
if print_it
|
89
|
+
seq.p
|
90
|
+
else
|
91
|
+
seq_to_a
|
92
|
+
end
|
13
93
|
|
14
94
|
What's with _#map_?
|
15
95
|
=================
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/lib/functional.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
class ::Regexp
|
3
2
|
class NegRegexp
|
4
3
|
def initialize r
|
@@ -21,57 +20,100 @@ class ::Regexp
|
|
21
20
|
end
|
22
21
|
|
23
22
|
class ::Object
|
24
|
-
def
|
23
|
+
def to_fun meth = nil
|
25
24
|
Functional.new self, meth
|
26
25
|
end
|
27
|
-
|
26
|
+
end
|
27
|
+
|
28
|
+
class Counter
|
29
|
+
include Enumerable
|
30
|
+
attr_reader :c
|
31
|
+
|
32
|
+
def initialize first = nil, step = nil
|
33
|
+
@c, @step = first || 0, step || 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def next; @c += @step end
|
37
|
+
def to_i; c.to_i end
|
38
|
+
def to_f; c.to_f end
|
39
|
+
|
40
|
+
def + i
|
41
|
+
@c += @step*i
|
42
|
+
end
|
43
|
+
|
44
|
+
def each &e
|
45
|
+
loop { e.call self; self.next }
|
46
|
+
end
|
28
47
|
end
|
29
48
|
|
30
49
|
class Functional
|
31
50
|
include Enumerable
|
32
51
|
|
52
|
+
class DEFAULT
|
53
|
+
end
|
54
|
+
|
33
55
|
class Base
|
34
56
|
attr_reader :exe
|
35
57
|
attr_accessor :next
|
58
|
+
attr_reader :caller
|
59
|
+
|
36
60
|
def initialize &e
|
61
|
+
@caller = Kernel.caller.first
|
37
62
|
@exe = e
|
38
63
|
end
|
39
64
|
|
40
|
-
def
|
65
|
+
def base_fun *a
|
41
66
|
@next.call *a
|
42
67
|
end
|
68
|
+
alias call base_fun
|
43
69
|
|
44
70
|
def end
|
45
71
|
@next.end
|
46
72
|
end
|
47
73
|
|
74
|
+
def clean
|
75
|
+
@next.clean
|
76
|
+
end
|
77
|
+
|
48
78
|
def to_proc
|
49
79
|
method( :call).to_proc
|
50
80
|
end
|
51
81
|
end
|
52
82
|
|
53
83
|
class Collect <Base
|
54
|
-
def
|
84
|
+
def collect_fun *a
|
55
85
|
@next.call *@exe.call( *a)
|
56
86
|
end
|
87
|
+
alias call collect_fun
|
88
|
+
end
|
89
|
+
|
90
|
+
class Tap <Base
|
91
|
+
def tap_fun *a
|
92
|
+
@exe.call *a
|
93
|
+
@next.call *a
|
94
|
+
end
|
95
|
+
alias call tap_fun
|
57
96
|
end
|
58
97
|
|
59
98
|
class Select <Base
|
60
|
-
def
|
99
|
+
def select_fun *a
|
61
100
|
@next.call *a if @exe.call *a
|
62
101
|
end
|
102
|
+
alias call select_fun
|
63
103
|
end
|
64
104
|
|
65
|
-
class
|
66
|
-
def
|
105
|
+
class Filter <Base
|
106
|
+
def filter_fun *a
|
67
107
|
@next.call *a unless @exe.call *a
|
68
108
|
end
|
109
|
+
alias call filter_fun
|
69
110
|
end
|
70
111
|
|
71
112
|
class Compact <Base
|
72
|
-
def
|
113
|
+
def compact_fun *a
|
73
114
|
@next.call *a unless a.empty? || [nil] == a
|
74
115
|
end
|
116
|
+
alias call compact_fun
|
75
117
|
end
|
76
118
|
|
77
119
|
class BottomUp <Base
|
@@ -80,7 +122,7 @@ class Functional
|
|
80
122
|
@buffer, @start = nil, start
|
81
123
|
end
|
82
124
|
|
83
|
-
def
|
125
|
+
def bottom_up_fun a
|
84
126
|
if @exe.call a
|
85
127
|
@next.call @buffer+a
|
86
128
|
@buffer = @start.dup
|
@@ -88,6 +130,7 @@ class Functional
|
|
88
130
|
@buffer += a
|
89
131
|
end
|
90
132
|
end
|
133
|
+
alias call bottom_up_fun
|
91
134
|
|
92
135
|
def end
|
93
136
|
@next.call @buffer
|
@@ -101,7 +144,7 @@ class Functional
|
|
101
144
|
@buffer, @start = nil, start
|
102
145
|
end
|
103
146
|
|
104
|
-
def
|
147
|
+
def top_down_fun a
|
105
148
|
if @exe.call a
|
106
149
|
@next.call @buffer
|
107
150
|
@buffer = @start.dup+a
|
@@ -109,6 +152,7 @@ class Functional
|
|
109
152
|
@buffer += a
|
110
153
|
end
|
111
154
|
end
|
155
|
+
alias call top_down_fun
|
112
156
|
|
113
157
|
def end
|
114
158
|
@next.call @buffer
|
@@ -120,6 +164,7 @@ class Functional
|
|
120
164
|
def end
|
121
165
|
nil
|
122
166
|
end
|
167
|
+
alias :clean :end
|
123
168
|
end
|
124
169
|
|
125
170
|
class P <Each
|
@@ -130,16 +175,17 @@ class Functional
|
|
130
175
|
|
131
176
|
class Inject <Base
|
132
177
|
attr_reader :it
|
178
|
+
alias :end :it
|
179
|
+
|
133
180
|
def initialize start, *a, &e
|
134
181
|
super *a, &e
|
135
182
|
@it = start
|
136
183
|
end
|
137
|
-
|
184
|
+
|
185
|
+
def inject_fun *a
|
138
186
|
@it = @exe.call @it, *a
|
139
187
|
end
|
140
|
-
|
141
|
-
@it
|
142
|
-
end
|
188
|
+
alias call inject_fun
|
143
189
|
end
|
144
190
|
|
145
191
|
class To_a <Inject
|
@@ -149,21 +195,36 @@ class Functional
|
|
149
195
|
end
|
150
196
|
|
151
197
|
class Map <Collect
|
152
|
-
def
|
198
|
+
def map_fun *a
|
153
199
|
@exe.call *a, &@next
|
154
200
|
end
|
201
|
+
alias call map_fun
|
202
|
+
end
|
203
|
+
|
204
|
+
class Flatten <Base
|
205
|
+
def flatten_fun *a
|
206
|
+
a.each &@next.method( :call)
|
207
|
+
end
|
208
|
+
alias call flatten_fun
|
155
209
|
end
|
156
210
|
|
157
211
|
class Reduce <Base
|
158
|
-
def initialize iv, *a, &
|
159
|
-
super *a, &
|
160
|
-
|
161
|
-
@buf
|
212
|
+
def initialize iv = ::Functional::DEFAULT, *a, &exe
|
213
|
+
super *a, &exe
|
214
|
+
iv = Array.method :new if ::Functional::DEFAULT == iv
|
215
|
+
@buf = if iv.kind_of?( ::Proc) || iv.kind_of?( ::Method)
|
216
|
+
p default: :proc, iv: iv
|
217
|
+
Hash.new {|h,k| h[k] = iv.call }
|
218
|
+
else
|
219
|
+
p default: :value, iv: iv
|
220
|
+
{}.tap {|h| h.default = iv }
|
221
|
+
end
|
162
222
|
end
|
163
223
|
|
164
|
-
def
|
224
|
+
def reduce_fun *a
|
165
225
|
@buf[ a[0]] = @exe.call @buf[ a[0]], *a[1..-1]
|
166
226
|
end
|
227
|
+
alias call reduce_fun
|
167
228
|
|
168
229
|
def end
|
169
230
|
@buf.each {|i| @next.call *i}
|
@@ -171,6 +232,83 @@ class Functional
|
|
171
232
|
end
|
172
233
|
end
|
173
234
|
|
235
|
+
class Slice <Base
|
236
|
+
def initialize n
|
237
|
+
@buf, @n = [], n
|
238
|
+
end
|
239
|
+
|
240
|
+
def slice_fun *a
|
241
|
+
@buf.push a
|
242
|
+
unless @n > @buf.size
|
243
|
+
@next.call @buf
|
244
|
+
@buf.clear
|
245
|
+
end
|
246
|
+
end
|
247
|
+
alias call slice_fun
|
248
|
+
|
249
|
+
def end
|
250
|
+
@next.call @buf
|
251
|
+
@next.end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class Cons <Base
|
256
|
+
def initialize n
|
257
|
+
@buf, @n = [], n
|
258
|
+
end
|
259
|
+
|
260
|
+
def cons_fun *a
|
261
|
+
@buf.push a
|
262
|
+
unless @n > @buf.size
|
263
|
+
class <<self
|
264
|
+
def call *a
|
265
|
+
@buf.push a
|
266
|
+
@next.call @buf
|
267
|
+
@buf.shift
|
268
|
+
end
|
269
|
+
end
|
270
|
+
@next.call @buf
|
271
|
+
@buf.shift
|
272
|
+
end
|
273
|
+
end
|
274
|
+
alias call cons_fun
|
275
|
+
|
276
|
+
def end
|
277
|
+
@next.call @buf unless @n > @buf.size
|
278
|
+
@next.end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
class Pager <Base
|
283
|
+
def initialize *opts
|
284
|
+
@pager = IO.popen ENV['PAGER'] || 'less', 'w'
|
285
|
+
opts.each do |opt|
|
286
|
+
case opt.to_s
|
287
|
+
when *%w[inspect i] then alias call call_inspect
|
288
|
+
else raise ArgumentError, "Unknown opt: #{opt}"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def call_inspect *a
|
294
|
+
@pager.puts a.inspect
|
295
|
+
end
|
296
|
+
|
297
|
+
def pager_fun *a
|
298
|
+
@pager.puts a
|
299
|
+
end
|
300
|
+
alias call pager_fun
|
301
|
+
|
302
|
+
def clean
|
303
|
+
@pager.close
|
304
|
+
end
|
305
|
+
|
306
|
+
def end
|
307
|
+
clean
|
308
|
+
nil
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
174
312
|
attr_accessor :next, :stack, :obj, :func, :args
|
175
313
|
|
176
314
|
def initialize obj = nil, func = nil, *args
|
@@ -190,7 +328,7 @@ class Functional
|
|
190
328
|
push Map.new( &exe)
|
191
329
|
end
|
192
330
|
|
193
|
-
def reduce iv, &exe
|
331
|
+
def reduce iv = ::Functional::DEFAULT, &exe
|
194
332
|
push Reduce.new( iv, &exe)
|
195
333
|
end
|
196
334
|
|
@@ -202,8 +340,8 @@ class Functional
|
|
202
340
|
push Select.new( &re.method( :match))
|
203
341
|
end
|
204
342
|
|
205
|
-
def
|
206
|
-
push
|
343
|
+
def filter &exe
|
344
|
+
push Filter.new( &exe)
|
207
345
|
end
|
208
346
|
|
209
347
|
def compact
|
@@ -218,6 +356,10 @@ class Functional
|
|
218
356
|
push TopDown.new( init, &exe)
|
219
357
|
end
|
220
358
|
|
359
|
+
def flatten &exe
|
360
|
+
push Flatten.new
|
361
|
+
end
|
362
|
+
|
221
363
|
def each &exe
|
222
364
|
return self unless exe
|
223
365
|
push Each.new
|
@@ -233,37 +375,61 @@ class Functional
|
|
233
375
|
def run
|
234
376
|
@obj.send @func||:each, *@args, &@next #.method(:call)
|
235
377
|
@next.end
|
378
|
+
rescue Object
|
379
|
+
@next.clean
|
380
|
+
raise $!
|
236
381
|
end
|
237
382
|
|
238
383
|
def p
|
239
|
-
each
|
384
|
+
each &Kernel.method( :p)
|
240
385
|
end
|
241
|
-
end
|
242
386
|
|
243
|
-
|
244
|
-
|
387
|
+
def pager *opts
|
388
|
+
push Pager.new( *opts)
|
389
|
+
run
|
390
|
+
end
|
245
391
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
alias emit putdup
|
250
|
-
alias call emit
|
251
|
-
end
|
392
|
+
def sort &exe
|
393
|
+
to_a.sort &exe
|
394
|
+
end
|
252
395
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
396
|
+
def sort_by &exe
|
397
|
+
to_a.sort_by &exe
|
398
|
+
end
|
399
|
+
|
400
|
+
# [ _A, _B, ..., _C, ..., _D ] ==> [ [0, _A], [1, _B], ..., [_I, _C], ..., [_N, _D]]
|
401
|
+
# [ [_A|_As], [_B|_Bs], ..., [_C|_Cs], ..., [_D|_Ds] ] ==> [ [0,_A|_As], [1,_B|_Bs], ..., [_I,_C|_Cs], ..., [_N,_D|_Ds] ]
|
402
|
+
def with_index &exe
|
403
|
+
i = 0
|
404
|
+
exe ||= Array.method :[]
|
405
|
+
push Collect.new {|*a| exe.call i, *a }
|
406
|
+
end
|
407
|
+
|
408
|
+
def slice n, &e
|
409
|
+
push Slice.new( n)
|
410
|
+
push Collect.new( &e) if e
|
411
|
+
self
|
412
|
+
end
|
413
|
+
|
414
|
+
def cons n, &e
|
415
|
+
push Cons.new( n)
|
416
|
+
push Collect.new( &e) if e
|
417
|
+
self
|
418
|
+
end
|
419
|
+
|
420
|
+
class Save < Base
|
421
|
+
attr_reader :db
|
257
422
|
|
258
|
-
def
|
259
|
-
|
423
|
+
def initialize db
|
424
|
+
@db = db
|
260
425
|
end
|
261
426
|
|
262
|
-
def
|
263
|
-
|
427
|
+
def call k, *v
|
428
|
+
@db[ k] = v.length == 1 ? v.first : v
|
264
429
|
end
|
265
430
|
end
|
266
431
|
|
267
|
-
|
268
|
-
|
269
|
-
end
|
432
|
+
def save db
|
433
|
+
push Save.new( db)
|
434
|
+
end
|
435
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 3
|
9
|
+
version: 0.1.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Denis Knauf
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-11-24 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -38,11 +38,12 @@ homepage: http://github.com/DenisKnauf/functional
|
|
38
38
|
licenses: []
|
39
39
|
|
40
40
|
post_install_message:
|
41
|
-
rdoc_options:
|
42
|
-
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
43
|
require_paths:
|
44
44
|
- lib
|
45
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
46
47
|
requirements:
|
47
48
|
- - ">="
|
48
49
|
- !ruby/object:Gem::Version
|
@@ -50,6 +51,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
51
|
- 0
|
51
52
|
version: "0"
|
52
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
53
55
|
requirements:
|
54
56
|
- - ">="
|
55
57
|
- !ruby/object:Gem::Version
|
@@ -59,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
61
|
requirements: []
|
60
62
|
|
61
63
|
rubyforge_project:
|
62
|
-
rubygems_version: 1.3.
|
64
|
+
rubygems_version: 1.3.7
|
63
65
|
signing_key:
|
64
66
|
specification_version: 3
|
65
67
|
summary: Makes big functional operations possible
|