enumerable_lz 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8ad8aeb48998541b0d13a8e20a63aa5d2b6af5ba
4
+ data.tar.gz: 7f66a110548e37e864bee992327c67ad36580dd4
5
+ SHA512:
6
+ metadata.gz: b7847ff329ce9a00831d66525d7dc5f91fadbe4f33a3a249dcc1cea959eaef37795ab0648e127be80b26ae1a3a83d913a304aa9670b2f76d7269b379a5f9fcbe
7
+ data.tar.gz: 5511760da227ab917f450a4c9c2af7475d5e88923a374de2d8b1a780edb909fcc1b30b81d9b3c79f5c560e881c22c9a831a4ac900c80f4e1f49487ace01aa745
data/ChangeLog CHANGED
@@ -14,3 +14,9 @@
14
14
 
15
15
  * Improve performance much more
16
16
 
17
+ == 0.1.5 / 2014-01-08
18
+
19
+ * Add `filter.with_index` and `transform.with_index` feature
20
+ * Add `filter.with_initializer` feature (and obsolete `filter_with_initproc` method)
21
+ * Add support for Ruby 2.0.0/2.1.0
22
+ * Improve performance
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2011 GOTOH Shunsuke (@antimon2)
3
+ Copyright (c) 2011,2014 GOTOH Shunsuke (@antimon2)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -9,17 +9,32 @@ Also it provides lazy equivalents of some methods in `Enumerable`.
9
9
  When require 'enumerable_lz', these lazy methods are provided:
10
10
 
11
11
  * `Enumerable#filter`
12
- * `Enumerable#filter_with_initproc`
13
12
  * `Enumerable#transform`
14
13
 
15
- For example (in Ruby 1.9.x):
14
+ And some method-chains are provided:
15
+
16
+ * `Enumerable#filter.with_index`
17
+ * `Enumerable#filter.with_initializer`
18
+ * `Enumerable#transform.with_index`
19
+
20
+ For example (in Ruby 1.9.x or greater):
16
21
 
17
22
  require 'enumerable_lz'
18
23
  require 'prime'
19
-
24
+
20
25
  (1..Float::INFINITY).transform{|n|n**2+1}.filter{|m|m.prime?}.take(100)
21
26
  # => [2, 5, ... , 682277, 739601] for a few msec.
22
27
 
28
+ Prime.filter.with_index{|q,i|i.odd?}.take(10)
29
+ # => [3, 7, 13, 19, 29, 37, 43, 53, 61, 71]
30
+
31
+ Prime.transform.with_index{|q,i|[q,i]}.take(10)
32
+ # => [[2, 0], [3, 1], [5, 2], [7, 3], [11, 4], [13, 5], [17, 6], [19, 7], [23, 8], [29, 9]]
33
+
34
+ # especially, when calling transform.with_index without a block
35
+ Prime.transform.with_index.take(10)
36
+ # => [[2, 0], [3, 1], [5, 2], [7, 3], [11, 4], [13, 5], [17, 6], [19, 7], [23, 8], [29, 9]]
37
+
23
38
 
24
39
  ## Expanded Usage
25
40
 
@@ -37,7 +52,7 @@ When require 'enumerable_lz/enumerable_ex', some lazy methods equivalents to ori
37
52
  * `Enumerable#take_while_lz`
38
53
 
39
54
 
40
- For example (in Ruby 1.9.x):
55
+ For example (in Ruby 1.9.x or greater):
41
56
 
42
57
  require 'enumerable_lz'
43
58
  require 'enumerable_lz/enumerable_ex'
@@ -51,10 +66,12 @@ These expanded methods are inplemented with fundamental filter and transformatio
51
66
 
52
67
  ## Supported Rubies
53
68
 
54
- * Ruby 1.9.x (testing 1.9.2 p-180)
55
- * Ruby 1.8.7 (testing 1.8.7-p334)
56
- * JRuby (testing 1.5.6, 1.6.0)
57
- * MacRuby (testing 0.9)
69
+ * Ruby 2.1.0 (testing 2.1.0-p0)
70
+ * Ruby 2.0.0 (testing 2.0.0-p247)
71
+ * Ruby 1.9.x (testing 1.9.3-p448)
72
+ * Ruby 1.8.7 (testing 1.8.7-p358)
73
+ * JRuby (testing 1.7.2)
74
+ * MacRuby (testing 0.12)
58
75
 
59
76
  ## Installation
60
77
 
@@ -64,6 +81,6 @@ These expanded methods are inplemented with fundamental filter and transformatio
64
81
  ## License
65
82
 
66
83
  The MIT License
67
- Copyright (c) 2011 GOTOH Shunsuke (@antimon2)
84
+ Copyright (c) 2011, 2014 GOTOH Shunsuke (@antimon2)
68
85
 
69
86
  Please see [LICENSE.txt](LICENSE.txt) for details.
data/lib/enumerable_lz.rb CHANGED
@@ -11,8 +11,48 @@ else
11
11
  require File.dirname(__FILE__)+'/enumerable_lz/transform_18'
12
12
  end
13
13
 
14
+ # add {#filter} and {#transform} methods.
14
15
  module Enumerable
16
+ # @!group Fundamental Method Summary
17
+
18
+ # Filter by pattern or block
19
+ # @yield [el]
20
+ # @overload filter(&block)
21
+ # filter by block
22
+ # @yield [el] filterring block.
23
+ # @yieldparam el each element of original Enumerable
24
+ # @yieldreturn [Boolean]
25
+ # @return [Enumerator::Filter]
26
+ # @overload filter(pattern)
27
+ # filter by pattern
28
+ # @param [#===] pattern filterring pattern. (uses === method)
29
+ # @return [Enumerator::Filter]
30
+ # @return [Enumerator::Filter]
31
+ def filter pattern = nil, &block
32
+ Enumerator::Filter.new self, pattern||block
33
+ end
34
+
35
+ # @yield [el]
36
+ # @deprecated Use filter.with_initializer instead of this method
37
+ # @see Enumerator::Filter#with_initializer
38
+ # @return [Enumerator::Filter]
39
+ def filter_with_initproc init_proc, pattern = nil, &block
40
+ filter.with_initializer init_proc, pattern = nil, &block
41
+ end
42
+
43
+ # Transform by block
44
+ # @yield [el] transform block.
45
+ # @yieldparam el each element of original Enumerable
46
+ # @yieldreturn [Object]
47
+ # @return [Enumerator::Transform]
48
+ def transform &block
49
+ Enumerator::Transform.new self, &block
50
+ end
51
+
52
+ # @!endgroup
53
+
54
+ # @private
15
55
  module EnumerableLz
16
- VERSION = "0.1.4"
56
+ VERSION = "0.1.5"
17
57
  end
18
- end
58
+ end
@@ -1,49 +1,91 @@
1
1
  require File.expand_path('..', __FILE__)
2
2
 
3
3
  module Enumerable
4
+ # @!group Expanded Method Summary
5
+
6
+ # lazy equivalent of `Enumerable#select`
7
+ # @yield [el]
8
+ # @note available only requiring "enumerable_lz/enumerable_ex"
9
+ # @return [Enumerator::Filter]
4
10
  def select_lz &block
5
11
  filter &block
6
12
  end
7
-
8
13
  alias :find_all_lz :select_lz
9
14
 
15
+ # lazy equivalent of `Enumerable#reject`
16
+ # @yield [el]
17
+ # @note available only requiring "enumerable_lz/enumerable_ex"
18
+ # @return [Enumerator::Filter]
10
19
  def reject_lz &block
11
20
  filter {|e|!block.call(e)}
12
21
  end
13
22
 
23
+ # lazy equivalent of `Enumerable#grep`
24
+ # @yield [el]
25
+ # @note available only requiring "enumerable_lz/enumerable_ex"
26
+ # @overload grep_lz(pattern)
27
+ # @return [Enumerator::Filter]
28
+ # @overload grep_lz(pattern, &block)
29
+ # @yield [el]
30
+ # @return [Enumerator::Transform]
31
+ # @return [Enumerator::Filter, Enumerator::Transform]
14
32
  def grep_lz pattern, &block
15
33
  enum = filter pattern
16
34
  block_given? ? enum.transform(&block) : enum
17
35
  end
18
36
 
19
- alias :map_lz :transform
37
+ # @!method map_lz(&block)
38
+ # lazy equivalent of `Enumerable#map`
39
+ # @yield [el]
40
+ # @note available only requiring "enumerable_lz/enumerable_ex"
41
+ # @return [Enumerator::Transform]
42
+ self.__send__(:alias_method, :map_lz, :transform)
20
43
  alias :collect_lz :map_lz
21
44
 
45
+ # lazy equivalent of `Enumerable#drop`
46
+ # @note available only requiring "enumerable_lz/enumerable_ex"
47
+ # @return [Enumerator::Filter]
22
48
  def drop_lz n
23
49
  raise ArgumentError, "attempt to take negative size" if n < 0
24
50
  # each_with_index.filter{|el,idx|idx >= n}.transform{|el,idx|el}
25
- cnt = 0
26
- filter_with_initproc(Proc.new{cnt=0}) {|el| (cnt+=1) > n}
51
+ # cnt = 0
52
+ # filter_with_initproc(Proc.new{cnt=0}) {|el| (cnt+=1) > n}
53
+ filter.with_index {|el, i| i >= n}
27
54
  end
28
55
 
56
+ # lazy equivalent of `Enumerable#drop_while`
57
+ # @yield [el]
58
+ # @note available only requiring "enumerable_lz/enumerable_ex"
59
+ # @return [Enumerator::Filter]
29
60
  def drop_while_lz &block
30
61
  return self if !block_given?
31
62
  flg = false
32
- filter_with_initproc(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
63
+ # filter_with_initproc(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
64
+ filter.with_initializer(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
33
65
  end
34
66
 
67
+ # lazy equivalent of `Enumerable#take`
68
+ # @note available only requiring "enumerable_lz/enumerable_ex"
69
+ # @return [Enumerator::Filter]
35
70
  def take_lz n
36
71
  raise ArgumentError, "attempt to take negative size" if n < 0
37
72
  # each_with_index.filter{|el,idx|throw :do_break if idx >= n;true}.transform{|el,idx|el}
38
- cnt = 0
39
- filter_with_initproc(Proc.new{cnt=0}) {|el| throw :do_break if (cnt+=1) > n;true}
73
+ # cnt = 0
74
+ # filter_with_initproc(Proc.new{cnt=0}) {|el| throw :do_break if (cnt+=1) > n;true}
75
+ filter.with_index {|el, i| throw :do_break if i >= n; true}
40
76
  end
41
77
 
78
+ # lazy equivalent of `Enumerable#take_while`
79
+ # @yield [el]
80
+ # @note available only requiring "enumerable_lz/enumerable_ex"
81
+ # @return [Enumerator::Filter]
42
82
  def take_while_lz &block
43
83
  return self if !block_given?
44
- filter {|el|throw :do_break unless block.call(el);true}
84
+ filter {|el|throw :do_break unless block.call(el); true}
45
85
  end
46
86
 
87
+ # @!endgroup
88
+
47
89
  # def zip_lz *lists
48
90
  # enums = lists.map{|list|list.each rescue [].each}
49
91
  # Enumerator.new do |y|
@@ -1,21 +1,14 @@
1
- # for Ruby1.9.x except for MacRuby
2
- module Enumerable
3
- def filter pattern = nil, &block
4
- Filter.new self, pattern||block
5
- end
6
-
7
- def filter_with_initproc init_proc, pattern = nil, &block
8
- Filter.new self, init_proc, pattern||block
9
- end
1
+ # -- for Ruby1.9.x except for MacRuby
10
2
 
3
+ # add [Filter] and [Transform] classes.
4
+ class Enumerator
5
+ # Lazy Filterring Enumerator
11
6
  class Filter < Enumerator
12
- def initialize obj, *args
13
- the_filter = args.shift
14
- init_block, the_filter = [the_filter, args.shift] unless args.empty?
7
+ # @param [Enumerable] obj an Enumerable.
8
+ # @param [#===] the_filter filterring pattern or proc.
9
+ def initialize obj, the_filter=nil
15
10
  @org_enum = obj
16
- @init_block = init_block unless init_block.nil?
17
11
  super() do |y|
18
- @init_block.call unless @init_block.nil?
19
12
  compiled_filter = @filter.nil? ? Proc.new{true} : lambda{|f|
20
13
  break f[0] if f.size==1
21
14
  codes = f.size.times.map do |idx|
@@ -32,6 +25,9 @@ module Enumerable
32
25
  filter! the_filter if the_filter
33
26
  end
34
27
 
28
+ # Apply filter pattern/block and return self. (bang method of filter)
29
+ # @yield [el]
30
+ # @return [Filter] self
35
31
  def filter! pattern=nil, &block
36
32
  @filter||=[]
37
33
  if pattern.is_a? Array
@@ -42,9 +38,15 @@ module Enumerable
42
38
  self
43
39
  end
44
40
 
45
- #[override]
41
+ # [override] for performance
42
+ # @yield [el]
43
+ # @overload filter(&block)
44
+ # @yield [el]
45
+ # @overload filter(pattern)
46
+ # @param [#===] pattern
47
+ # @see Enumerable#filter Enumerable#filter
48
+ # @return [Filter]
46
49
  def filter pattern=nil, &block
47
- return super unless @init_block.nil?
48
50
  # clone.filter! pattern, &block
49
51
  patterns = @filter.nil? ? [] : @filter.clone
50
52
  if pattern.is_a? Array
@@ -55,6 +57,33 @@ module Enumerable
55
57
  Filter.new @org_enum, patterns
56
58
  end
57
59
 
60
+ # @overload with_initializer(init_proc, &block)
61
+ # filter by block with initializer proc.
62
+ # @param [#call] init_proc initializer proc. (uses .call method)
63
+ # @yield filterring block.
64
+ # @return [Filter]
65
+ # @overload with_initializer(init_proc, pattern)
66
+ # filter by pattern with initializer proc.
67
+ # @param [#call] init_proc initializer proc. (uses .call method)
68
+ # @param [#===] pattern filterring pattern. (uses === method)
69
+ # @return [Filter]
70
+ # @return [Filter]
71
+ def with_initializer init_proc, pattern = nil, &block
72
+ src_enum = @filter.nil? ? @org_enum : self
73
+ FilterWithInitializer.new src_enum, init_proc, pattern||block
74
+ end
75
+
76
+ # @param [Numeric] offset offset.
77
+ # @yield [el, i]
78
+ # @return [Filter]
79
+ def with_index offset=0, &block
80
+ raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
81
+ i = offset - 1
82
+ with_initializer(Proc.new{i = offset - 1}) do |el|
83
+ block.call(el, i += 1)
84
+ end
85
+ end
86
+
58
87
  private
59
88
  def conv_proc pattern
60
89
  case pattern
@@ -65,9 +94,31 @@ module Enumerable
65
94
  end
66
95
  end
67
96
  end
97
+
98
+ # @api private
99
+ class FilterWithInitializer < Filter
100
+ def initialize obj, init_block, the_filter = nil
101
+ super obj, the_filter
102
+ @initializer = init_block
103
+ end
104
+
105
+ def each &block
106
+ return self unless block_given?
107
+ @initializer.call
108
+ super &block
109
+ end
110
+
111
+ # @see Enumerable#filter Enumerable#filter
112
+ # @return [Filter]
113
+ def filter pattern=nil, &block
114
+ Filter.new self, pattern||block
115
+ end
116
+ end
117
+ private_constant :FilterWithInitializer if self.respond_to? :private_constant
68
118
  end
69
- #against the Bug on JRuby <1.6.2
119
+ # against the Bug on JRuby < 1.6.2
70
120
  if !(Proc.new{true}===true)
121
+ # @private
71
122
  class Proc
72
123
  alias :=== :call
73
124
  end
@@ -1,76 +1,99 @@
1
1
  # for Ruby1.8.7
2
+
2
3
  module Enumerable
3
- def filter pattern = nil, &block
4
- Filter.new self, pattern||block
5
- end
4
+ class Enumerator
5
+ class Filter < Enumerator
6
+ def initialize obj, the_filter=nil
7
+ filter! the_filter if the_filter
8
+ @org_enum = obj
9
+ end
6
10
 
7
- def filter_with_initproc init_proc, pattern = nil, &block
8
- Filter.new self, init_proc, pattern||block
9
- end
11
+ def each &block
12
+ return self unless block_given?
13
+ # compiled_filter = (@filter||[Proc.new{true}]).inject do |r,f|
14
+ # Proc.new{|el| r[el] && f[el]}
15
+ # end
16
+ compiled_filter = @filter.nil? ? Proc.new{true} : lambda{|f|
17
+ break f[0] if f.size==1
18
+ codes = f.size.times.map do |idx|
19
+ "f[#{idx}][el]"
20
+ end
21
+ eval "Proc.new{|el|"+codes.join(" && ")+"}"
22
+ }.call(@filter)
23
+ catch :do_break do
24
+ @org_enum.each do |el|
25
+ block.call(el) if compiled_filter[el]
26
+ end
27
+ end
28
+ self
29
+ end
10
30
 
11
- class Filter < Enumerator
12
- def initialize obj, *args
13
- the_filter = args.shift
14
- init_block, the_filter = [the_filter, args.shift] unless args.empty?
15
- filter! the_filter if the_filter
16
- @org_enum = obj
17
- @init_block = init_block unless init_block.nil?
18
- end
31
+ def filter! pattern=nil, &block
32
+ @filter||=[]
33
+ if pattern.is_a? Array
34
+ pattern.each{|el| @filter << conv_proc(el)}
35
+ else
36
+ @filter << conv_proc(pattern || block)
37
+ end
38
+ self
39
+ end
19
40
 
20
- def each &block
21
- return self unless block_given?
22
- @init_block.call unless @init_block.nil?
23
- # compiled_filter = (@filter||[Proc.new{true}]).inject do |r,f|
24
- # Proc.new{|el| r[el] && f[el]}
25
- # end
26
- compiled_filter = @filter.nil? ? Proc.new{true} : lambda{|f|
27
- break f[0] if f.size==1
28
- codes = f.size.times.map do |idx|
29
- "f[#{idx}][el]"
41
+ #[override]
42
+ def filter pattern=nil, &block
43
+ # clone.filter! pattern, &block
44
+ patterns = @filter.nil? ? [] : @filter.clone
45
+ if pattern.is_a? Array
46
+ patterns.push(*pattern)
47
+ else
48
+ patterns << (pattern || block)
30
49
  end
31
- eval "Proc.new{|el|"+codes.join(" && ")+"}"
32
- }.call(@filter)
33
- catch :do_break do
34
- @org_enum.each do |el|
35
- block.call(el) if compiled_filter[el]
50
+ Filter.new @org_enum, patterns
51
+ end
52
+
53
+ def with_initializer init_proc, pattern = nil, &block
54
+ src_enum = @filter.nil? ? @org_enum : self
55
+ FilterWithInitializer.new src_enum, init_proc, pattern||block
56
+ end
57
+
58
+ #[override]
59
+ def with_index offset=0, &block
60
+ raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
61
+ i = offset - 1
62
+ with_initializer(Proc.new{i = offset - 1}) do |el|
63
+ block.call(el, i += 1)
36
64
  end
37
65
  end
38
- self
39
- end
40
66
 
41
- def filter! pattern=nil, &block
42
- @filter||=[]
43
- if pattern.is_a? Array
44
- pattern.each{|el| @filter << conv_proc(el)}
45
- else
46
- @filter << conv_proc(pattern || block)
67
+ private
68
+ def conv_proc pattern
69
+ case pattern
70
+ when nil
71
+ Proc.new{true}
72
+ when Proc
73
+ pattern
74
+ else
75
+ pattern.respond_to?(:to_proc) ? pattern.to_proc : Proc.new{|el|pattern===el}
76
+ end
47
77
  end
48
- self
49
78
  end
50
79
 
51
- #[override]
52
- def filter pattern=nil, &block
53
- return super unless @init_block.nil?
54
- # clone.filter! pattern, &block
55
- patterns = @filter.nil? ? [] : @filter.clone
56
- if pattern.is_a? Array
57
- patterns.push(*pattern)
58
- else
59
- patterns << (pattern || block)
80
+ # private
81
+ class FilterWithInitializer < Filter
82
+ def initialize obj, init_block, the_filter = nil
83
+ super obj, the_filter
84
+ @initializer = init_block
85
+ end
86
+
87
+ def each &block
88
+ return self unless block_given?
89
+ @initializer.call
90
+ super &block
60
91
  end
61
- Filter.new @org_enum, patterns
62
- end
63
92
 
64
- private
65
- def conv_proc pattern
66
- case pattern
67
- when nil
68
- Proc.new{true}
69
- when Proc
70
- pattern
71
- else
72
- pattern.respond_to?(:to_proc) ? pattern.to_proc : Proc.new{|el|pattern===el}
93
+ #[override]
94
+ def filter pattern=nil, &block
95
+ Filter.new self, pattern||block
73
96
  end
74
97
  end
75
98
  end
76
- end
99
+ end
@@ -1,24 +1,15 @@
1
1
  # for MacRuby
2
- module Enumerable
3
- def filter pattern = nil, &block
4
- Filter.new self, pattern||block
5
- end
6
-
7
- def filter_with_initproc init_proc, pattern = nil, &block
8
- Filter.new self, init_proc, pattern||block
9
- end
10
2
 
3
+ class Enumerator
11
4
  class Filter < Enumerator
12
- def initialize obj, *args
13
- the_filter = args.shift
14
- init_block, the_filter = [the_filter, args.shift] unless args.empty?
5
+ TrueProc = Proc.new{true}
6
+
7
+ def initialize obj, the_filter = nil
15
8
  @org_enum = obj
16
- @init_block = init_block unless init_block.nil?
17
9
  outer = self
18
10
  super Class.new {
19
11
  define_method :each do
20
12
  return outer unless block_given?
21
- init_block.call unless init_block.nil?
22
13
  compiled_filter = outer.__send__(:compile_filter)
23
14
  catch :do_break do
24
15
  obj.each do |el|
@@ -50,10 +41,23 @@ module Enumerable
50
41
  else
51
42
  patterns<<(pattern || block)
52
43
  end
53
- return Filter.new @org_enum, @init_block, patterns unless @init_block.nil?
54
44
  Filter.new @org_enum, patterns
55
45
  end
56
46
 
47
+ def with_initializer init_proc, pattern = nil, &block
48
+ src_enum = @filter.nil? ? @org_enum : self
49
+ FilterWithInitializer.new src_enum, init_proc, pattern||block
50
+ end
51
+
52
+ #[override]
53
+ def with_index offset=0, &block
54
+ raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
55
+ i = offset - 1
56
+ patterns = @filter.nil? ? [] : @filter.clone
57
+ patterns << Proc.new{|el| block.call(el, i += 1)}
58
+ FilterWithInitializer.new @org_enum, Proc.new{i = offset - 1}, patterns
59
+ end
60
+
57
61
  private
58
62
  def conv_proc pattern
59
63
  case pattern
@@ -74,4 +78,23 @@ module Enumerable
74
78
  }.call(@filter)
75
79
  end
76
80
  end
81
+
82
+ # private
83
+ class FilterWithInitializer < Filter
84
+ def initialize obj, init_block, the_filter = nil
85
+ super obj, the_filter
86
+ @initializer = init_block
87
+ end
88
+
89
+ def each &block
90
+ return self unless block_given?
91
+ @initializer.call
92
+ super &block
93
+ end
94
+
95
+ #[override]
96
+ def filter pattern=nil, &block
97
+ Filter.new self, pattern||block
98
+ end
99
+ end
77
100
  end
@@ -1,10 +1,11 @@
1
- # for Ruby1.9.x except for MacRuby
2
- module Enumerable
3
- def transform &block
4
- Transform.new self, &block
5
- end
1
+ # -- for Ruby1.9.x except for MacRuby
6
2
 
3
+ # add [Filter] and [Transform] classes.
4
+ class Enumerator
5
+ # Lazy Transform Enumerator
7
6
  class Transform < Enumerator
7
+ # @param [Enumerable] obj an Enumerable.
8
+ # @yield transform block.
8
9
  def initialize obj, &transformer
9
10
  @org_enum = obj
10
11
  super() do |y|
@@ -16,13 +17,19 @@ module Enumerable
16
17
  transform! &transformer if block_given?
17
18
  end
18
19
 
20
+ # Apply another transformer block and return self. (bang method of transform)
21
+ # @yield [el] transform block.
22
+ # @return [Transform] self
19
23
  def transform! &block
20
24
  @transformer||=[]
21
25
  @transformer << block if block_given?
22
26
  self
23
27
  end
24
28
 
25
- #[override]
29
+ # [override] for performance
30
+ # @yield [el] transform block.
31
+ # @see Enumerable#transform Enumerable#transform
32
+ # @return [Transform]
26
33
  def transform &block
27
34
  # clone.transform! &block
28
35
  cp = Transform.new @org_enum
@@ -32,6 +39,22 @@ module Enumerable
32
39
  cp.transform! &block
33
40
  end
34
41
 
42
+ # @yield [el, i]
43
+ # @overload with_index(offset=0, &block)
44
+ # @param [Numeric] offset offset.
45
+ # @yield [el, i]
46
+ # @return [Transform]
47
+ # @overload with_index(offset=0)
48
+ # @note same as with_index(offset) {|el, i| [el, i]}
49
+ # @param [Numeric] offset offset.
50
+ # @return [Transform]
51
+ # @return [Transform]
52
+ def with_index offset=0, &block
53
+ src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
54
+ block ||= Proc.new{|el, i|[el, i]}
55
+ TransformWithIndex.new src_enum, offset, &block
56
+ end
57
+
35
58
  private
36
59
  def compile_transformer
37
60
  return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
@@ -44,4 +67,30 @@ module Enumerable
44
67
  }.call(@transformer)
45
68
  end
46
69
  end
70
+
71
+ # @api private
72
+ class TransformWithIndex < Transform
73
+ def initialize obj, offset = 0, &transformer
74
+ @org_enum = obj
75
+ @transformer = transformer.nil? ? nil : [transformer]
76
+ @offset = offset
77
+ end
78
+
79
+ def each
80
+ return self unless block_given?
81
+ the_transformer = @transformer[0] || Proc.new{|el,i|el}
82
+ i = @offset - 1
83
+ @org_enum.each do |el|
84
+ yield the_transformer.call(el, i+=1)
85
+ end
86
+ end
87
+
88
+ # @see Enumerable#filter Enumerable#filter
89
+ # @return [Transform]
90
+ def transform &block
91
+ Transform.new self, &block
92
+ end
93
+ alias :transform! :transform
94
+ end
95
+ private_constant :TransformWithIndex if self.respond_to? :private_constant
47
96
  end
@@ -1,50 +1,79 @@
1
1
  # for Ruby1.8.7
2
2
  module Enumerable
3
- def transform &block
4
- Transform.new self, &block
5
- end
3
+ class Enumerator
4
+ class Transform < Enumerator
5
+ def initialize obj, &transformer
6
+ @org_enum = obj
7
+ transform! &transformer if block_given?
8
+ end
6
9
 
7
- class Transform < Enumerator
8
- def initialize obj, &transformer
9
- @org_enum = obj
10
- transform! &transformer if block_given?
11
- end
10
+ def each &block
11
+ return self unless block_given?
12
+ the_transformer = compile_transformer
13
+ @org_enum.each do |el|
14
+ block.call the_transformer[el]
15
+ end
16
+ self
17
+ end
12
18
 
13
- def each &block
14
- return self unless block_given?
15
- the_transformer = compile_transformer
16
- @org_enum.each do |el|
17
- block.call the_transformer[el]
19
+ def transform! &block
20
+ @transformer||=[]
21
+ @transformer << block if block_given?
22
+ self
18
23
  end
19
- self
20
- end
21
24
 
22
- def transform! &block
23
- @transformer||=[]
24
- @transformer << block if block_given?
25
- self
26
- end
25
+ #[override]
26
+ def transform &block
27
+ # clone.transform! &block
28
+ cp = Transform.new @org_enum
29
+ @transformer.each do |org_block|
30
+ cp.transform! &org_block
31
+ end unless @transformer.nil?
32
+ cp.transform! &block
33
+ end
27
34
 
28
- #[override]
29
- def transform &block
30
- # clone.transform! &block
31
- cp = Transform.new @org_enum
32
- @transformer.each do |org_block|
33
- cp.transform! &org_block
34
- end unless @transformer.nil?
35
- cp.transform! &block
35
+ #[override]
36
+ def with_index offset=0, &block
37
+ src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
38
+ block ||= Proc.new{|el, i|[el, i]}
39
+ TransformWithIndex.new src_enum, offset, &block
40
+ end
41
+
42
+ private
43
+ def compile_transformer
44
+ return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
45
+ return @transformer[0] if @transformer.size==1
46
+ lambda{|t|
47
+ codes = t.size.times.inject "el" do |r,idx|
48
+ "t[#{idx}][#{r}]"
49
+ end
50
+ eval "Proc.new{|el|"+codes+"}"
51
+ }.call(@transformer)
52
+ end
36
53
  end
37
54
 
38
- private
39
- def compile_transformer
40
- return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
41
- return @transformer[0] if @transformer.size==1
42
- lambda{|t|
43
- codes = t.size.times.inject "el" do |r,idx|
44
- "t[#{idx}][#{r}]"
55
+ # private
56
+ class TransformWithIndex < Transform
57
+ def initialize obj, offset = 0, &transformer
58
+ @org_enum = obj
59
+ @transformer = transformer.nil? ? nil : [transformer]
60
+ @offset = offset
61
+ end
62
+
63
+ def each
64
+ return self unless block_given?
65
+ the_transformer = @transformer[0] || Proc.new{|el,i|el}
66
+ i = @offset - 1
67
+ @org_enum.each do |el|
68
+ yield the_transformer.call(el, i+=1)
45
69
  end
46
- eval "Proc.new{|el|"+codes+"}"
47
- }.call(@transformer)
70
+ end
71
+
72
+ #[override]
73
+ def transform &block
74
+ Transform.new self, &block
75
+ end
76
+ alias :transform! :transform
48
77
  end
49
78
  end
50
79
  end
@@ -1,9 +1,5 @@
1
1
  # for MacRuby
2
- module Enumerable
3
- def transform &block
4
- Transform.new self, &block
5
- end
6
-
2
+ class Enumerator
7
3
  class Transform < Enumerator
8
4
  def initialize obj, &transformer
9
5
  @org_enum = obj
@@ -36,6 +32,13 @@ module Enumerable
36
32
  cp.transform! &block
37
33
  end
38
34
 
35
+ #[override]
36
+ def with_index offset=0, &block
37
+ src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
38
+ block ||= Proc.new{|el, i|[el, i]}
39
+ TransformWithIndex.new src_enum, offset, &block
40
+ end
41
+
39
42
  private
40
43
  def compile_transformer
41
44
  return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
@@ -52,4 +55,28 @@ module Enumerable
52
55
  # }.call(@transformer)
53
56
  end
54
57
  end
58
+
59
+ # private
60
+ class TransformWithIndex < Transform
61
+ def initialize obj, offset = 0, &transformer
62
+ @org_enum = obj
63
+ @transformer = transformer.nil? ? nil : [transformer]
64
+ @offset = offset
65
+ end
66
+
67
+ def each
68
+ return self unless block_given?
69
+ the_transformer = @transformer[0] || Proc.new{|el,i|el}
70
+ i = @offset - 1
71
+ @org_enum.each do |el|
72
+ yield the_transformer.call(el, i+=1)
73
+ end
74
+ end
75
+
76
+ #[override]
77
+ def transform &block
78
+ Transform.new self, &block
79
+ end
80
+ alias :transform! :transform
81
+ end
55
82
  end
data/test/test_filter.rb CHANGED
@@ -3,15 +3,17 @@ require 'enumerable_lz'
3
3
 
4
4
  class FilterTest < Test::Unit::TestCase
5
5
  def test_instance
6
- enum = Enumerable::Filter.new []
6
+ filter_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Filter : Enumerator::Filter
7
+ enum = filter_class.new []
7
8
  assert_not_nil(enum)
8
9
  assert_kind_of(Enumerable, enum)
9
10
  end
10
11
 
11
12
  def test_filter_array
13
+ filter_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Filter : Enumerator::Filter
12
14
  array = %w[Yes I have a number]
13
15
  enum = array.filter{|letters|letters.size > 1}
14
- assert_instance_of(Enumerable::Filter, enum)
16
+ assert_instance_of(filter_class, enum)
15
17
  assert_equal(%w[Yes have number], enum.to_a)
16
18
  end
17
19
 
@@ -85,14 +87,15 @@ class FilterTest < Test::Unit::TestCase
85
87
  assert_same(enum1, enum2)
86
88
  end
87
89
 
88
- def test_init_block
89
- range = -10..10
90
- cnt = 0
91
- init_pr = Proc.new{cnt = 0}
92
- filter_pr = Proc.new{(cnt+=1)<=10}
93
- enum = Enumerable::Filter.new range, init_pr, filter_pr
94
- assert_equal([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1], enum.to_a)
95
- end
90
+ # def test_init_block
91
+ # range = -10..10
92
+ # cnt = 0
93
+ # init_pr = Proc.new{cnt = 0}
94
+ # filter_pr = Proc.new{(cnt+=1)<=10}
95
+ # # enum = Enumerator::FilterWithInitializer.new range, init_pr, filter_pr
96
+ # enum = Enumerator::FilterWithInitializer.new range, init_pr, filter_pr
97
+ # assert_equal([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1], enum.to_a)
98
+ # end
96
99
 
97
100
  def test_filter_with_initproc_1
98
101
  range = -10..10
@@ -122,4 +125,22 @@ class FilterTest < Test::Unit::TestCase
122
125
  enum = range.filter_with_initproc(init_pr) {|n|throw :do_break if (sum+=n)>100;true}
123
126
  assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], enum.to_a)
124
127
  end
128
+
129
+ def test_filetr_with_index
130
+ a = 0
131
+ b = (1..10).filter.with_index{|n,i|a=n;i.even?}.first
132
+ assert_equal([1, 1], [a, b])
133
+ end
134
+
135
+ def test_filetr_with_index_2
136
+ a = 0
137
+ b = (1..10).filter.with_index(1){|n,i|a=n;i.even?}.first
138
+ assert_equal([2, 2], [a, b])
139
+ end
140
+
141
+ def test_filetr_with_index_no_block
142
+ assert_raise(ArgumentError) do
143
+ (1..10).filter.with_index(2).take(2)
144
+ end
145
+ end
125
146
  end
@@ -3,15 +3,17 @@ require 'enumerable_lz'
3
3
 
4
4
  class TransformTest < Test::Unit::TestCase
5
5
  def test_instance
6
- enum = Enumerable::Transform.new []
6
+ transform_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Transform : Enumerator::Transform
7
+ enum = transform_class.new []
7
8
  assert_not_nil(enum)
8
9
  assert_kind_of(Enumerable, enum)
9
10
  end
10
11
 
11
12
  def test_transform_array
13
+ transform_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Transform : Enumerator::Transform
12
14
  array = %w[Yes I have a number]
13
15
  enum = array.transform{|letters|letters.swapcase}
14
- assert_instance_of(Enumerable::Transform, enum)
16
+ assert_instance_of(transform_class, enum)
15
17
  assert_equal(%w[yES i HAVE A NUMBER], enum.to_a)
16
18
  end
17
19
 
@@ -52,4 +54,24 @@ class TransformTest < Test::Unit::TestCase
52
54
  enum2 = enum1.transform!
53
55
  assert_same(enum1, enum2)
54
56
  end
57
+
58
+ def test_transform_with_index
59
+ range = -10..10
60
+ a = 0
61
+ result = range.transform.with_index{|n,i|n+a=i}.take(10)
62
+ assert_equal(9, a)
63
+ end
64
+
65
+ def test_transform_with_index2
66
+ range = -10..10
67
+ a = 0
68
+ result = range.transform.with_index{|n,i|n+a=i}.take(10)
69
+ assert_equal([-10, -8, -6, -4, -2, 0, 2, 4, 6, 8], result)
70
+ end
71
+
72
+ def test_transform_with_index_no_block
73
+ range = -10..10
74
+ result = range.transform.with_index(2).filter{|n,i|n+i<10}.to_a
75
+ assert_equal([[-10, 2], [-9, 3], [-8, 4], [-7, 5], [-6, 6], [-5, 7], [-4, 8], [-3, 9], [-2, 10]], result)
76
+ end
55
77
  end
metadata CHANGED
@@ -1,28 +1,22 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: enumerable_lz
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.1.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - antimon2
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
-
13
- date: 2011-05-07 00:00:00 +09:00
14
- default_executable:
11
+ date: 2014-01-08 00:00:00.000000000 Z
15
12
  dependencies: []
16
-
17
- description: Add Enumerable#filter, Enumerable#transform and some equivalent methods on Enumerable with suffix '_lz'.
13
+ description: Add Enumerable#filter, Enumerable#transform and some equivalent methods
14
+ on Enumerable with suffix '_lz'.
18
15
  email: antimon2.me@gmail.com
19
16
  executables: []
20
-
21
17
  extensions: []
22
-
23
18
  extra_rdoc_files: []
24
-
25
- files:
19
+ files:
26
20
  - README.md
27
21
  - LICENSE.txt
28
22
  - ChangeLog
@@ -38,35 +32,35 @@ files:
38
32
  - lib/enumerable_lz/transform_18.rb
39
33
  - lib/enumerable_lz/transform_mrb.rb
40
34
  - lib/enumerable_lz.rb
41
- has_rdoc: true
42
35
  homepage: https://github.com/antimon2/enumerable_lz
43
36
  licenses: []
44
-
37
+ metadata: {}
45
38
  post_install_message:
46
- rdoc_options: []
47
-
48
- require_paths:
39
+ rdoc_options:
40
+ - --no-private
41
+ - --exclude
42
+ - (_mrb|_18)
43
+ require_paths:
49
44
  - lib
50
- required_ruby_version: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
55
49
  version: 1.8.7
56
- required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
62
55
  requirements: []
63
-
64
56
  rubyforge_project: enumerable_lz
65
- rubygems_version: 1.5.3
57
+ rubygems_version: 2.0.3
66
58
  signing_key:
67
59
  specification_version: 3
68
- summary: Add Enumerable#filter, Enumerable#transform and some equivalent methods on Enumerable with suffix '_lz'.
69
- test_files:
60
+ summary: Add Enumerable#filter, Enumerable#transform and some equivalent methods on
61
+ Enumerable with suffix '_lz'.
62
+ test_files:
70
63
  - test/test_enumerable_ex.rb
71
64
  - test/test_filter.rb
72
65
  - test/test_transform.rb
66
+ has_rdoc: yard