enumerable_fu 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,50 +1,84 @@
1
1
  EnumerableFu
2
2
  ============
3
3
 
4
- "EnumerableFu" extends `Enumerable` with "lazy" versions of various operations,
5
- allowing streamed processing of large (or even infinite) collections.
4
+ Lazy "filtering" and transforming
5
+ ---------------------------------
6
6
 
7
- It also provides some interesting ways of combining Enumerables.
7
+ EnumerableFu extends Enumerable with "lazy" versions of various common operations:
8
8
 
9
- Filters
10
- -------
9
+ * `#selecting` selects elements that pass a test block (like `Enumerable#select`)
10
+ * `#rejecting` selects elements that fail a test block (like `Enumerable#reject`)
11
+ * `#collecting` applies a transforming block to each element (like `Enumerable#collect`)
12
+ * `#uniqing` discards duplicates (like `Enumerable#uniq`)
11
13
 
12
- `selecting` (cf. `select`, or `find_all`) returns each element for which the given block is true
14
+ We say the "...ing" variants are "lazy", because they defer per-element processing until the result is used. They return Enumerable "result proxy" objects, rather than Arrays, and only perform the actual filtering (or transformation) as the result proxy is enumerated.
13
15
 
14
- (1..6).selecting { |x| x.even? } # generates: 2, 4, 6
16
+ Perhaps an example would help. Consider the following snippet:
15
17
 
16
- `rejecting` (cf. `reject`) returns each element for which the given block is false:
18
+ >> (1..10).collect { |x| puts "#{x}^2 = #{x*x}"; x*x }.take_while { |x| x < 20 }
19
+ 1^2 = 1
20
+ 2^2 = 4
21
+ 3^2 = 9
22
+ 4^2 = 16
23
+ 5^2 = 25
24
+ 6^2 = 36
25
+ 7^2 = 49
26
+ 8^2 = 64
27
+ 9^2 = 81
28
+ 10^2 = 100
29
+ => [1, 4, 9, 16]
30
+
31
+ Here we use plain old `#collect` to square a bunch of numbers, and then grab the ones less than 20. We can do the same thing using `#collecting`, rather than `#collect`:
17
32
 
18
- (1..6).rejecting { |x| x.even? } # generates: 1, 3, 5
33
+ >> (1..10).collecting { |x| puts "#{x}^2 = #{x*x}"; x*x }.take_while { |x| x < 20 }
34
+ 1^2 = 1
35
+ 2^2 = 4
36
+ 3^2 = 9
37
+ 4^2 = 16
38
+ 5^2 = 25
39
+ => [1, 4, 9, 16]
19
40
 
20
- `collecting` (cf. `collect`, or `map`) applies a block to each element:
41
+ Same result, but notice how only the first five inputs were ever squared; just enough to find the first result above 20.
21
42
 
22
- [1,2,3].collecting { |x| x*2 } # generates: 2, 4, 6
43
+ Lazy pipelines
44
+ --------------
23
45
 
24
- `uniqing` (cf. `uniq`) returns unique elements:
46
+ By combining two or more of the lazy operations provided by EnumerableFu, you can create an efficient "pipeline", e.g.
25
47
 
26
- [2,1,2,3,2,1].uniqing # generates: 2, 1, 3
48
+ # enumerate all users
49
+ users = User.to_enum(:find_each)
27
50
 
28
- Unlike the original methods, the "...ing" variants each return an immutable Enumerable object, rather than an Array. The actual processing is deferred until the result Enumerable is enumerated (e.g. with `each`), and elements are produced "just in time".
51
+ # where first and last names start with the same letter
52
+ users = users.selecting { |u| u.first_name[0] == u.last_name[0] }
29
53
 
30
- Mixers
31
- ------
54
+ # grab their company (weeding out duplicates)
55
+ companies = users.collecting(&:company).uniqing
32
56
 
33
- `Enumerable.zipping` pulls elements from a number of Enumerables in parallel, yielding each group.
57
+ # resolve
58
+ companies.to_a #=> ["Disney"]
59
+
60
+ Because each processing step proceeds in parallel, without creation of intermediate collections (Arrays), you can efficiently operate on large (or even infinite) Enumerable collections.
61
+
62
+ Lazy combination of Enumerables
63
+ -------------------------------
64
+
65
+ EnumerableFu also provides some interesting ways to combine several Enumerable collections to create a new collection. Again, these operate "lazily".
66
+
67
+ `EnumerableFu.zipping` pulls elements from a number of collections in parallel, yielding each group.
34
68
 
35
69
  array1 = [1,3,6]
36
70
  array2 = [2,4,7]
37
- Enumerable.zipping(array1, array2) # generates: [1,2], [3,4], [6,7]
71
+ EnumerableFu.zipping(array1, array2) # generates: [1,2], [3,4], [6,7]
38
72
 
39
- `Enumerable.merging` merges multiple Enumerables, preserving sort-order. The inputs are assumed to be sorted already.
73
+ `EnumerableFu.merging` merges multiple collections, preserving sort-order. The inputs are assumed to be sorted already.
40
74
 
41
75
  array1 = [1,4,5]
42
76
  array2 = [2,3,6]
43
- Enumerable.merging(array1, array2) # generates: 1, 2, 3, 4, 5, 6
77
+ EnumerableFu.merging(array1, array2) # generates: 1, 2, 3, 4, 5, 6
44
78
 
45
- Variant `Enumerable.merging_by` uses a block to determine sort-order.
79
+ Variant `EnumerableFu.merging_by` uses a block to determine sort-order.
46
80
 
47
81
  array1 = %w(a dd cccc)
48
82
  array2 = %w(eee bbbbb)
49
- Enumerable.merging_by(array1, array2) { |x| x.length }
83
+ EnumerableFu.merging_by(array1, array2) { |x| x.length }
50
84
  # generates: %w(a dd eee cccc bbbbb)
@@ -57,7 +57,7 @@ module EnumerableFu
57
57
 
58
58
  end
59
59
 
60
- class << Enumerable
60
+ class << EnumerableFu
61
61
 
62
62
  def merging(*enumerables)
63
63
  EnumerableFu::Merger.new(enumerables)
@@ -1,3 +1,3 @@
1
1
  module EnumerableFu
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.1".freeze
3
3
  end
@@ -27,7 +27,7 @@ module EnumerableFu
27
27
 
28
28
  end
29
29
 
30
- class << Enumerable
30
+ class << EnumerableFu
31
31
 
32
32
  def zipping(*enumerables)
33
33
  EnumerableFu::Zipper.new(enumerables)
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Enumerable, :needs_enumerators => true do
3
+ describe EnumerableFu, :needs_enumerators => true do
4
4
 
5
5
  describe ".merging" do
6
6
 
@@ -8,14 +8,14 @@ describe Enumerable, :needs_enumerators => true do
8
8
  @array1 = [1,3,6]
9
9
  @array2 = [2,4,7]
10
10
  @array3 = [5,8]
11
- @merge = Enumerable.merging(@array1, @array2, @array3)
11
+ @merge = EnumerableFu.merging(@array1, @array2, @array3)
12
12
  @merge.to_a.should == [1,2,3,4,5,6,7,8]
13
13
  end
14
14
 
15
15
  it "is lazy" do
16
16
  @enum1 = [1,3]
17
17
  @enum2 = [2,4].with_time_bomb
18
- @merge = Enumerable.merging(@enum1, @enum2)
18
+ @merge = EnumerableFu.merging(@enum1, @enum2)
19
19
  @merge.take(4).should == [1,2,3,4]
20
20
  end
21
21
 
@@ -26,7 +26,7 @@ describe Enumerable, :needs_enumerators => true do
26
26
  it "uses the block to determine order" do
27
27
  @array1 = %w(cccc dd a)
28
28
  @array2 = %w(eeeee bbb)
29
- @merge = Enumerable.merging_by(@array1, @array2) { |s| -s.length }
29
+ @merge = EnumerableFu.merging_by(@array1, @array2) { |s| -s.length }
30
30
  @merge.to_a.should == %w(eeeee cccc bbb dd a)
31
31
  end
32
32
 
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Enumerable, :needs_enumerators => true do
3
+ describe EnumerableFu, :needs_enumerators => true do
4
4
 
5
5
  describe "#zipping" do
6
6
 
@@ -8,12 +8,12 @@ describe Enumerable, :needs_enumerators => true do
8
8
  @array1 = [1,3,6]
9
9
  @array2 = [2,4,7]
10
10
  @array3 = [5,8]
11
- @zip = Enumerable.zipping(@array1, @array2, @array3)
11
+ @zip = EnumerableFu.zipping(@array1, @array2, @array3)
12
12
  @zip.to_a.should == [[1,2,5], [3,4,8], [6,7,nil]]
13
13
  end
14
14
 
15
15
  it "is lazy" do
16
- @zip = Enumerable.zipping(%w(a b c), [1,2].with_time_bomb)
16
+ @zip = EnumerableFu.zipping(%w(a b c), [1,2].with_time_bomb)
17
17
  @zip.take(2).should == [["a", 1], ["b", 2]]
18
18
  end
19
19
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: enumerable_fu
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.1.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mike Williams
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-14 00:00:00 +10:00
13
+ date: 2011-04-24 00:00:00 +10:00
14
14
  default_executable:
15
15
  dependencies: []
16
16