marcandre-backports 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +16 -0
- data/README.rdoc +8 -1
- data/VERSION.yml +2 -2
- data/lib/backports.rb +1 -1
- data/lib/backports/array.rb +24 -0
- data/lib/backports/enumerable.rb +55 -2
- data/lib/backports/hash.rb +4 -0
- data/test/backports_test.rb +127 -65
- metadata +2 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
= Packable --- History
|
2
2
|
|
3
|
+
== Version 1.2 - April 12, 2009
|
4
|
+
|
5
|
+
* Array
|
6
|
+
* +reverse_each+
|
7
|
+
* +cycle+
|
8
|
+
|
9
|
+
* Enumerable
|
10
|
+
* +reverse_each+
|
11
|
+
* +each_slice+, +each_cons+
|
12
|
+
* +count+
|
13
|
+
* +cycle+
|
14
|
+
* +group_by+
|
15
|
+
|
16
|
+
* Hash
|
17
|
+
* <tt>default_proc=</tt>
|
18
|
+
|
3
19
|
== Version 1.1 - April 11, 2009
|
4
20
|
|
5
21
|
* Array
|
data/README.rdoc
CHANGED
@@ -39,18 +39,25 @@ Works with ruby 1.8 & 1.9
|
|
39
39
|
* +key+
|
40
40
|
* +symbolize_keys+, <tt>symbolize_keys!</tt>
|
41
41
|
* +reverse_merge+, <tt>reverse_merge!</tt>
|
42
|
+
* <tt>default_proc=</tt>
|
42
43
|
* Enumerable
|
43
44
|
* +sum+
|
44
45
|
* +find_index+
|
45
46
|
* +take+, +take_while+, +drop+, +drop_while+
|
46
47
|
* +first+
|
48
|
+
* +reverse_each+
|
49
|
+
* +count+
|
50
|
+
* +cycle+
|
51
|
+
* +group_by+
|
47
52
|
* Array
|
48
53
|
* +flatten+, <tt>flatten!</tt>
|
49
54
|
* +find_index+, +find+
|
55
|
+
* +reverse_each+
|
56
|
+
* +cycle+
|
50
57
|
* Fixnum
|
51
58
|
* <tt>odd?</tt>, <tt>even?</tt>
|
52
59
|
|
53
|
-
Finally, there is no need to <tt>require 'enumerator'</tt> in older ruby, and +Enumerator+ can be accessed directly (instead of <tt>Enumerable::Enumerator</
|
60
|
+
Finally, there is no need to <tt>require 'enumerator'</tt> in older ruby, and +Enumerator+ can be accessed directly (instead of <tt>Enumerable::Enumerator</tt>)
|
54
61
|
|
55
62
|
= License
|
56
63
|
|
data/VERSION.yml
CHANGED
data/lib/backports.rb
CHANGED
@@ -10,6 +10,6 @@ module Kernel
|
|
10
10
|
end unless method_defined? :require_relative
|
11
11
|
end
|
12
12
|
|
13
|
-
%w(object module enumerable
|
13
|
+
%w(object module array enumerable string symbol fixnum hash).each do |lib|
|
14
14
|
require_relative "backports/#{lib}"
|
15
15
|
end
|
data/lib/backports/array.rb
CHANGED
@@ -56,4 +56,28 @@ class Array
|
|
56
56
|
alias_method_chain :index, :block
|
57
57
|
alias_method :find_index, :index
|
58
58
|
end
|
59
|
+
|
60
|
+
# rindex
|
61
|
+
unless ([1].rindex{true} rescue false)
|
62
|
+
def rindex_with_block(*arg)
|
63
|
+
return rindex_without_block(*arg) unless block_given? && arg.empty?
|
64
|
+
reverse_each.each_with_index{|o,i| return size - 1 - i if yield o}
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
alias_method_chain :rindex, :block
|
68
|
+
end
|
69
|
+
|
70
|
+
unless ([1].reverse_each rescue false)
|
71
|
+
def reverse_each_with_optional_block(&block)
|
72
|
+
return reverse_each_without_optional_block(&block) if block_given?
|
73
|
+
to_enum(:reverse_each)
|
74
|
+
end
|
75
|
+
alias_method_chain :reverse_each, :optional_block
|
76
|
+
end
|
77
|
+
|
78
|
+
def cycle(*arg, &block)
|
79
|
+
return to_enum(:cycle, *arg) unless block_given?
|
80
|
+
nb = arg.empty? ? (1/0.0) : arg.first
|
81
|
+
nb.to_i.times{each(&block)}
|
82
|
+
end unless method_defined? :cycle
|
59
83
|
end
|
data/lib/backports/enumerable.rb
CHANGED
@@ -40,7 +40,7 @@ module Enumerable
|
|
40
40
|
|
41
41
|
# Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
|
42
42
|
def take_while
|
43
|
-
|
43
|
+
return to_enum(:take_while) unless block_given?
|
44
44
|
inject([]) do |array, elem|
|
45
45
|
return array unless yield elem
|
46
46
|
array << elem
|
@@ -55,7 +55,7 @@ module Enumerable
|
|
55
55
|
|
56
56
|
# Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
|
57
57
|
def drop_while(&block)
|
58
|
-
|
58
|
+
return to_enum(:drop_while) unless block_given?
|
59
59
|
array = to_a
|
60
60
|
array.each_with_index do |element, i|
|
61
61
|
return array.drop(i) unless yield(element)
|
@@ -68,4 +68,57 @@ module Enumerable
|
|
68
68
|
arg.empty? ? take(1)[0] : take(arg.first)
|
69
69
|
end unless method_defined? :first
|
70
70
|
|
71
|
+
# Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
|
72
|
+
def reverse_each(&block)
|
73
|
+
return to_enum(:reverse_each) unless block_given?
|
74
|
+
# There is no other way then to convert to an array first... see 1.9's source.
|
75
|
+
to_a.reverse_each(&block)
|
76
|
+
self
|
77
|
+
end unless method_defined? :reverse_each
|
78
|
+
|
79
|
+
# Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
|
80
|
+
unless ((1..2).each_slice(1) rescue false)
|
81
|
+
def each_slice_with_optional_block(len, &block)
|
82
|
+
raise ArgumentError, "invalid slice size" if len <= 0
|
83
|
+
return to_enum(:each_slice, len) unless block_given?
|
84
|
+
each_slice_without_optional_block(len, &block)
|
85
|
+
end
|
86
|
+
alias_method_chain :each_slice, :optional_block
|
87
|
+
end
|
88
|
+
|
89
|
+
def count(*arg)
|
90
|
+
result = 0
|
91
|
+
if block_given?
|
92
|
+
each{|o| result += 1 if yield o}
|
93
|
+
elsif arg.empty?
|
94
|
+
each{|o| result += 1}
|
95
|
+
else
|
96
|
+
obj = arg.first
|
97
|
+
each{|o| result += 1 if obj == o}
|
98
|
+
end
|
99
|
+
result
|
100
|
+
end unless method_defined? :count
|
101
|
+
|
102
|
+
def cycle(*arg, &block)
|
103
|
+
return to_enum(:cycle, *arg) unless block_given?
|
104
|
+
to_a.cycle(*arg, &block)
|
105
|
+
end unless method_defined? :cycle
|
106
|
+
|
107
|
+
unless ((1..2).each_cons(1) rescue false)
|
108
|
+
def each_cons_with_optional_block(len, &block)
|
109
|
+
raise ArgumentError, "invalid size" if len <= 0
|
110
|
+
return to_enum(:each_cons, len) unless block_given?
|
111
|
+
each_cons_without_optional_block(len, &block)
|
112
|
+
end
|
113
|
+
alias_method_chain :each_cons, :optional_block
|
114
|
+
end
|
115
|
+
|
116
|
+
def group_by
|
117
|
+
return to_enum(:group_by) unless block_given?
|
118
|
+
returning({}) do |result|
|
119
|
+
each do |o|
|
120
|
+
result.fetch(yield o){|key| result[key] = []} << o
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end unless method_defined? :group_by
|
71
124
|
end
|
data/lib/backports/hash.rb
CHANGED
@@ -34,4 +34,8 @@ class Hash
|
|
34
34
|
replace(reverse_merge(other_hash))
|
35
35
|
end
|
36
36
|
|
37
|
+
# Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Hash.html]
|
38
|
+
def default_proc=(proc)
|
39
|
+
replace(Hash.new(&proc).merge!(self))
|
40
|
+
end unless method_defined? :default_proc=
|
37
41
|
end
|
data/test/backports_test.rb
CHANGED
@@ -1,63 +1,136 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class BackportsTest < Test::Unit::TestCase
|
4
|
-
context "
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
context "Enumerable" do
|
5
|
+
context "#find_index" do
|
6
|
+
should "conform to doc" do
|
7
|
+
assert_equal 3, %w{ant bat cat dog}.find_index {|item| item =~ /g/ }
|
8
|
+
assert_equal nil, %w{ant bat cat dog}.find_index {|item| item =~ /h/ }
|
9
|
+
end
|
10
|
+
|
11
|
+
should "#work for enumerables too" do
|
12
|
+
assert_equal 69-42, (42..666).find_index(69)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
|
-
|
11
|
-
|
16
|
+
context "#take" do
|
17
|
+
should "conform to doc" do
|
18
|
+
assert_equal [1, 2, 3], (1..7).take(3)
|
19
|
+
assert_equal [["a", 1], ["b", 2]], { 'a'=>1, 'b'=>2, 'c'=>3 }.take(2)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "only consume what's needed" do
|
23
|
+
assert_equal [], Enumerator.new(nil).take(0)
|
24
|
+
assert_raises(NoMethodError) { Enumerator.new(nil).take(1) }
|
25
|
+
end
|
12
26
|
end
|
13
|
-
|
27
|
+
|
28
|
+
context "#take_while" do
|
29
|
+
should "conform to doc" do
|
30
|
+
assert_equal [1,2], (1..7).take_while {|item| item < 3 }
|
31
|
+
assert_equal [2,4,6], [ 2, 4, 6, 9, 11, 16 ].take_while(&:even?)
|
32
|
+
end
|
14
33
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
assert_equal [["a", 1], ["b", 2]], { 'a'=>1, 'b'=>2, 'c'=>3 }.take(2)
|
34
|
+
should "work with infinite enumerables" do
|
35
|
+
assert_equal [1,2], (1..(1/0.0)).take_while {|item| item < 3 }
|
36
|
+
end
|
19
37
|
end
|
38
|
+
|
39
|
+
context "#drop" do
|
40
|
+
should "conform to doc" do
|
41
|
+
assert_equal [5, 8, 13], [ 1, 1, 2, 3, 5, 8, 13 ].drop(4)
|
42
|
+
assert_equal [], [ 1, 1, 2, 3, 5, 8, 13 ].drop(99)
|
43
|
+
end
|
20
44
|
|
21
|
-
|
22
|
-
|
23
|
-
|
45
|
+
should "work with enums" do
|
46
|
+
assert_equal [14,15], (10...16).drop(4)
|
47
|
+
end
|
24
48
|
end
|
25
|
-
end
|
26
49
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
50
|
+
context "#drop_while" do
|
51
|
+
should "conform to doc" do
|
52
|
+
assert_equal [8, 13], [ 1, 1, 2, 3, 5, 8, 13 ].drop_while {|item| item < 6 }
|
53
|
+
end
|
54
|
+
|
55
|
+
should "work with enums" do
|
56
|
+
assert_equal [14,15], (10...16).drop_while {|item| item < 14}
|
57
|
+
end
|
58
|
+
|
59
|
+
should "work with extemity cases" do
|
60
|
+
assert_equal [10,11,12,13,14,15], (10...16).drop_while {|item| false}
|
61
|
+
assert_equal [], (10...16).drop_while {|item| true}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "#reverse_each" do
|
66
|
+
should "work as expected" do
|
67
|
+
assert_equal [4,3,2], (1..4).reverse_each.take(3)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "#each_slice" do
|
72
|
+
should "conform to doc" do
|
73
|
+
res = []
|
74
|
+
(1..10).each_slice(4){|ar| res << ar}
|
75
|
+
assert_equal [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10]], res
|
76
|
+
assert_equal [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10]], (1..10).each_slice(4).to_a
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "#count" do
|
81
|
+
should "conform to doc" do
|
82
|
+
assert_equal 4, (1..4).count
|
83
|
+
assert_equal 1, (1..4).count(3)
|
84
|
+
assert_equal 2, (1..4).count{|obj| obj > 2 }
|
85
|
+
end
|
31
86
|
end
|
32
87
|
|
33
|
-
|
34
|
-
|
88
|
+
context "#cycle" do
|
89
|
+
should "conform to doc" do
|
90
|
+
assert_equal ["a", "b", "c", "a", "b", "c"], ('a'..'c').cycle(2).to_a
|
91
|
+
end
|
35
92
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
assert_equal [], [ 1, 1, 2, 3, 5, 8, 13 ].drop(99)
|
93
|
+
|
94
|
+
context "#each_cons" do
|
95
|
+
should "conform to doc" do
|
96
|
+
assert_equal [[1,2],[2,3],[3,4]], (1..4).each_cons(2).to_a
|
97
|
+
end
|
42
98
|
end
|
43
99
|
|
44
|
-
|
45
|
-
|
100
|
+
context "#group_by" do
|
101
|
+
should "conform to doc" do
|
102
|
+
x = (1..5).group_by{|item| item.even? ? :even : :odd }
|
103
|
+
assert_equal({:even => [2,4], :odd => [1,3,5]}, x)
|
104
|
+
assert_equal nil, x[:xyz]
|
105
|
+
end
|
46
106
|
end
|
47
|
-
end
|
107
|
+
end #Enumerable
|
48
108
|
|
49
|
-
context "
|
50
|
-
|
51
|
-
|
109
|
+
context "Array" do
|
110
|
+
context "#reverse_each" do
|
111
|
+
should "return an enumerator when no block is given" do
|
112
|
+
assert_equal [4,3,2], [1,2,3,4].reverse_each.take(3)
|
113
|
+
end
|
52
114
|
end
|
53
115
|
|
54
|
-
|
55
|
-
|
116
|
+
context "#flatten" do
|
117
|
+
should "conform to doc" do
|
118
|
+
s = [ 1, 2, 3 ] #=> [1, 2, 3]
|
119
|
+
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
|
120
|
+
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
|
121
|
+
assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a.flatten
|
122
|
+
a = [ 1, 2, [3, [4, 5] ] ]
|
123
|
+
assert_equal [1, 2, 3, [4, 5]], a.flatten(1)
|
124
|
+
end
|
56
125
|
end
|
57
126
|
|
58
|
-
|
59
|
-
|
60
|
-
|
127
|
+
context "#index" do
|
128
|
+
should "conform to doc" do
|
129
|
+
a = [ "a", "b", "c" ]
|
130
|
+
assert_equal 1, a.index("b")
|
131
|
+
assert_equal nil, a.index("z")
|
132
|
+
assert_equal 1, a.index{|x|x=="b"}
|
133
|
+
end
|
61
134
|
end
|
62
135
|
end
|
63
136
|
|
@@ -65,33 +138,22 @@ class BackportsTest < Test::Unit::TestCase
|
|
65
138
|
should "should be constructible from key value pairs" do
|
66
139
|
assert_equal({1 => 2, 3 => 4}, Hash[[[1,2],[3,4]]])
|
67
140
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
4.times {|n| assert_equal 2 << n, x.flatten(n).length}
|
84
|
-
assert_raises(ArgumentError) {x.flatten}
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context "index" do
|
89
|
-
should "conform to doc" do
|
90
|
-
a = [ "a", "b", "c" ]
|
91
|
-
assert_equal 1, a.index("b")
|
92
|
-
assert_equal nil, a.index("z")
|
93
|
-
assert_equal 1, a.index{|x|x=="b"}
|
141
|
+
|
142
|
+
context "#default_proc=" do
|
143
|
+
should "conform to doc" do
|
144
|
+
h = { :foo => :bar }
|
145
|
+
h.default = "Go fish"
|
146
|
+
h.default_proc=lambda do |hash, key|
|
147
|
+
key + key
|
148
|
+
end
|
149
|
+
assert_equal :bar, h[:foo]
|
150
|
+
assert_equal 4, h[2]
|
151
|
+
assert_equal "catcat", h["cat"]
|
152
|
+
h.default=nil
|
153
|
+
assert_equal nil, h[2]
|
154
|
+
assert_equal nil, h["cat"]
|
155
|
+
end
|
94
156
|
end
|
95
157
|
end
|
96
|
-
|
158
|
+
|
97
159
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marcandre-backports
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Marc-Andr\xC3\xA9 Lafortune"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-12 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|