hamster 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +18 -0
- data/README.rdoc +9 -4
- data/lib/hamster/hash.rb +7 -5
- data/lib/hamster/list.rb +30 -9
- data/lib/hamster/set.rb +8 -9
- data/lib/hamster/stack.rb +1 -1
- data/lib/hamster/trie.rb +10 -12
- data/lib/hamster/version.rb +1 -1
- data/spec/hamster/hash/delete_spec.rb +47 -0
- data/spec/hamster/hash/each_spec.rb +20 -16
- data/spec/hamster/hash/remove_spec.rb +38 -22
- data/spec/hamster/list/each_spec.rb +41 -37
- data/spec/hamster/list/init_spec.rb +2 -4
- data/spec/hamster/list/last_spec.rb +19 -5
- data/spec/hamster/list/product_spec.rb +48 -0
- data/spec/hamster/list/{reject_spec.rb → remove_spec.rb} +1 -1
- data/spec/hamster/list/sum_spec.rb +48 -0
- data/spec/hamster/list/union_spec.rb +1 -0
- data/spec/hamster/set/delete_spec.rb +47 -0
- data/spec/hamster/set/each_spec.rb +20 -16
- data/spec/hamster/set/remove_spec.rb +38 -22
- metadata +7 -5
- data/spec/hamster/hash/reject_spec.rb +0 -63
- data/spec/hamster/set/reject_spec.rb +0 -63
data/History.rdoc
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
=== 0.1.23 / 2010-01-11
|
|
2
|
+
|
|
3
|
+
* Implement List#product.
|
|
4
|
+
|
|
5
|
+
* Implement List#sum.
|
|
6
|
+
|
|
7
|
+
* Implement List#last.
|
|
8
|
+
|
|
9
|
+
* Implement List#init.
|
|
10
|
+
|
|
11
|
+
* Alias #reject as #remove.
|
|
12
|
+
|
|
13
|
+
* Alias #each as #foreach.
|
|
14
|
+
|
|
15
|
+
* Rename Hash#remove as Hash#delete.
|
|
16
|
+
|
|
17
|
+
* Rename Set#remove as Set#delete.
|
|
18
|
+
|
|
1
19
|
=== 0.1.22 / 2010-01-10
|
|
2
20
|
|
|
3
21
|
* Implement List#union (aliased as #|).
|
data/README.rdoc
CHANGED
|
@@ -81,14 +81,17 @@ The <tt>Hamster::Hash</tt> version on the other hand was unchanged from the orig
|
|
|
81
81
|
|
|
82
82
|
Well, I could show you one but I'd have to re-write--or at least wrap--most <tt>Hash</tt> methods to make it generic, or at least write some application-specific code that synchronised using a <tt>Mutex</tt> and ... well ... it's hard, I always make mistakes, I always end up with weird edge cases and race conditions so, I'll leave that as an exercise for you :)
|
|
83
83
|
|
|
84
|
-
And don't forget that even if threading isn't a concern for you, the safety provided by immutability is worth it.
|
|
84
|
+
And don't forget that even if threading isn't a concern for you, the safety provided by immutability is worth it, not to mention the lazy implementations.
|
|
85
85
|
|
|
86
|
-
==
|
|
86
|
+
== But doesn't Ruby 1.9 now support lazy behaviour using Enumerators?
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
Sure does but they're implemented using Fibers which can't be shared across threads. All Hamster types are inherently thread-safe and sharable.
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
Moreover, Ruby's Enumerable module always returns an array -- calling <tt>Set#filter</tt> returns an <tt>Array</tt> -- whereas Hamster classes are almost always closed under a given operation. That is, Calling <tt>#filter</tt> on <tt>Set</tt> will return a <tt>Set</tt>, on a <tt>List</tt> will return a <tt>List</tt>, etc.
|
|
91
|
+
|
|
92
|
+
== So, you mentioned Sets, Lists, and Stacks?
|
|
91
93
|
|
|
94
|
+
Indeed I did.
|
|
92
95
|
|
|
93
96
|
=== Lists
|
|
94
97
|
|
|
@@ -161,6 +164,8 @@ How is this even possible? It's possible because <tt>IO#to_list</tt> creates a l
|
|
|
161
164
|
|
|
162
165
|
=== Stacks
|
|
163
166
|
|
|
167
|
+
=== Sets
|
|
168
|
+
|
|
164
169
|
== Disclaimer
|
|
165
170
|
|
|
166
171
|
Hamster started out as a spike to prove a point and has since morphed into something I actually use. My primary concern has been to round out the functionality with good test coverage and clean, readable code.
|
data/lib/hamster/hash.rb
CHANGED
|
@@ -42,8 +42,8 @@ module Hamster
|
|
|
42
42
|
end
|
|
43
43
|
alias_method :[]=, :put
|
|
44
44
|
|
|
45
|
-
def
|
|
46
|
-
trie = @trie.
|
|
45
|
+
def delete(key)
|
|
46
|
+
trie = @trie.delete(key)
|
|
47
47
|
if trie.equal?(@trie)
|
|
48
48
|
self
|
|
49
49
|
else
|
|
@@ -55,6 +55,7 @@ module Hamster
|
|
|
55
55
|
return self unless block_given?
|
|
56
56
|
@trie.each { |entry| yield(entry.key, entry.value) }
|
|
57
57
|
end
|
|
58
|
+
alias_method :foreach, :each
|
|
58
59
|
|
|
59
60
|
def map
|
|
60
61
|
return self unless block_given?
|
|
@@ -85,11 +86,12 @@ module Hamster
|
|
|
85
86
|
alias_method :select, :filter
|
|
86
87
|
alias_method :find_all, :filter
|
|
87
88
|
|
|
88
|
-
def
|
|
89
|
+
def remove
|
|
89
90
|
return self unless block_given?
|
|
90
|
-
|
|
91
|
+
filter { |key, value| !yield(key, value) }
|
|
91
92
|
end
|
|
92
|
-
alias_method :
|
|
93
|
+
alias_method :reject, :remove
|
|
94
|
+
alias_method :delete_if, :remove
|
|
93
95
|
|
|
94
96
|
def any?
|
|
95
97
|
if block_given?
|
data/lib/hamster/list.rb
CHANGED
|
@@ -62,6 +62,7 @@ module Hamster
|
|
|
62
62
|
list = list.tail
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
|
+
alias_method :foreach, :each
|
|
65
66
|
|
|
66
67
|
def map(&block)
|
|
67
68
|
return self unless block_given?
|
|
@@ -90,11 +91,12 @@ module Hamster
|
|
|
90
91
|
alias_method :select, :filter
|
|
91
92
|
alias_method :find_all, :filter
|
|
92
93
|
|
|
93
|
-
def
|
|
94
|
+
def remove(&block)
|
|
94
95
|
return self unless block_given?
|
|
95
96
|
filter { |item| !yield(item) }
|
|
96
97
|
end
|
|
97
|
-
alias_method :
|
|
98
|
+
alias_method :reject, :remove
|
|
99
|
+
alias_method :delete_if, :remove
|
|
98
100
|
|
|
99
101
|
def take_while(&block)
|
|
100
102
|
return self unless block_given?
|
|
@@ -173,7 +175,7 @@ module Hamster
|
|
|
173
175
|
|
|
174
176
|
def partition(&block)
|
|
175
177
|
return self unless block_given?
|
|
176
|
-
Stream.new(filter(&block)) { Sequence.new(
|
|
178
|
+
Stream.new(filter(&block)) { Sequence.new(remove(&block)) }
|
|
177
179
|
end
|
|
178
180
|
|
|
179
181
|
def append(other)
|
|
@@ -226,10 +228,7 @@ module Hamster
|
|
|
226
228
|
end
|
|
227
229
|
|
|
228
230
|
def count(&block)
|
|
229
|
-
|
|
230
|
-
count = 0
|
|
231
|
-
each { |item| count += 1 if yield(item) }
|
|
232
|
-
count
|
|
231
|
+
filter(&block).size
|
|
233
232
|
end
|
|
234
233
|
|
|
235
234
|
def clear
|
|
@@ -270,6 +269,27 @@ module Hamster
|
|
|
270
269
|
end
|
|
271
270
|
alias_method :|, :union
|
|
272
271
|
|
|
272
|
+
def init
|
|
273
|
+
return EmptyList if tail.empty?
|
|
274
|
+
Stream.new(head) { tail.init }
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def last
|
|
278
|
+
list = self
|
|
279
|
+
while !list.tail.empty?
|
|
280
|
+
list = list.tail
|
|
281
|
+
end
|
|
282
|
+
list.head
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def product
|
|
286
|
+
reduce(1, &:*)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def sum
|
|
290
|
+
reduce(0, &:+)
|
|
291
|
+
end
|
|
292
|
+
|
|
273
293
|
def eql?(other)
|
|
274
294
|
return false unless other.is_a?(List)
|
|
275
295
|
|
|
@@ -398,10 +418,11 @@ module Hamster
|
|
|
398
418
|
alias_method :select, :filter
|
|
399
419
|
alias_method :find_all, :filter
|
|
400
420
|
|
|
401
|
-
def
|
|
421
|
+
def remove
|
|
402
422
|
self
|
|
403
423
|
end
|
|
404
|
-
alias_method :
|
|
424
|
+
alias_method :reject, :remove
|
|
425
|
+
alias_method :delete_if, :remove
|
|
405
426
|
|
|
406
427
|
def take_while
|
|
407
428
|
self
|
data/lib/hamster/set.rb
CHANGED
|
@@ -39,8 +39,8 @@ module Hamster
|
|
|
39
39
|
end
|
|
40
40
|
alias_method :<<, :add
|
|
41
41
|
|
|
42
|
-
def
|
|
43
|
-
trie = @trie.
|
|
42
|
+
def delete(key)
|
|
43
|
+
trie = @trie.delete(key)
|
|
44
44
|
if trie.equal?(@trie)
|
|
45
45
|
self
|
|
46
46
|
else
|
|
@@ -52,6 +52,7 @@ module Hamster
|
|
|
52
52
|
return self unless block_given?
|
|
53
53
|
@trie.each { |entry| yield(entry.key) }
|
|
54
54
|
end
|
|
55
|
+
alias_method :foreach, :each
|
|
55
56
|
|
|
56
57
|
def map
|
|
57
58
|
return self unless block_given?
|
|
@@ -82,11 +83,12 @@ module Hamster
|
|
|
82
83
|
alias_method :select, :filter
|
|
83
84
|
alias_method :find_all, :filter
|
|
84
85
|
|
|
85
|
-
def
|
|
86
|
+
def remove
|
|
86
87
|
return self unless block_given?
|
|
87
88
|
filter { |item| !yield(item) }
|
|
88
89
|
end
|
|
89
|
-
alias_method :
|
|
90
|
+
alias_method :reject, :remove
|
|
91
|
+
alias_method :delete_if, :remove
|
|
90
92
|
|
|
91
93
|
def any?
|
|
92
94
|
return any? { |item| item } unless block_given?
|
|
@@ -125,10 +127,7 @@ module Hamster
|
|
|
125
127
|
end
|
|
126
128
|
|
|
127
129
|
def count(&block)
|
|
128
|
-
|
|
129
|
-
count = 0
|
|
130
|
-
each { |item| count += 1 if yield(item) }
|
|
131
|
-
count
|
|
130
|
+
filter(&block).size
|
|
132
131
|
end
|
|
133
132
|
|
|
134
133
|
def head
|
|
@@ -167,7 +166,7 @@ module Hamster
|
|
|
167
166
|
alias_method :entries, :to_a
|
|
168
167
|
|
|
169
168
|
def to_list
|
|
170
|
-
reduce(
|
|
169
|
+
reduce(EmptyList) { |list, item| list.cons(item) }
|
|
171
170
|
end
|
|
172
171
|
|
|
173
172
|
def inspect
|
data/lib/hamster/stack.rb
CHANGED
data/lib/hamster/trie.rb
CHANGED
|
@@ -10,9 +10,7 @@ module Hamster
|
|
|
10
10
|
|
|
11
11
|
# Returns the number of key-value pairs in the trie.
|
|
12
12
|
def size
|
|
13
|
-
|
|
14
|
-
each { count += 1 }
|
|
15
|
-
count
|
|
13
|
+
reduce(0) { |memo, item| memo.succ }
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
# Returns <tt>true</tt> if the trie contains no key-value pairs.
|
|
@@ -40,7 +38,7 @@ module Hamster
|
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
def filter
|
|
43
|
-
reduce(self) { |trie, entry| yield(entry) ? trie : trie.
|
|
41
|
+
reduce(self) { |trie, entry| yield(entry) ? trie : trie.delete(entry.key) }
|
|
44
42
|
end
|
|
45
43
|
|
|
46
44
|
# Returns a copy of <tt>self</tt> with the given value associated with the key.
|
|
@@ -77,9 +75,9 @@ module Hamster
|
|
|
77
75
|
end
|
|
78
76
|
end
|
|
79
77
|
|
|
80
|
-
# Returns a copy of <tt>self</tt> with the given key (and associated value)
|
|
81
|
-
def
|
|
82
|
-
|
|
78
|
+
# Returns a copy of <tt>self</tt> with the given key (and associated value) deleted. If not found, returns <tt>self</tt>.
|
|
79
|
+
def delete(key)
|
|
80
|
+
find_and_delete(key) || Trie.new(@significant_bits)
|
|
83
81
|
end
|
|
84
82
|
|
|
85
83
|
def include?(key, value)
|
|
@@ -109,15 +107,15 @@ module Hamster
|
|
|
109
107
|
# Returns a replacement instance after removing the specified key.
|
|
110
108
|
# If not found, returns <tt>self</tt>.
|
|
111
109
|
# If empty, returns <tt>nil</tt>.
|
|
112
|
-
def
|
|
110
|
+
def find_and_delete(key)
|
|
113
111
|
index = index_for(key)
|
|
114
112
|
entry = @entries[index]
|
|
115
113
|
if entry && entry.key.eql?(key)
|
|
116
|
-
return
|
|
114
|
+
return delete_at(index)
|
|
117
115
|
else
|
|
118
116
|
child = @children[index]
|
|
119
117
|
if child
|
|
120
|
-
copy = child.
|
|
118
|
+
copy = child.find_and_delete(key)
|
|
121
119
|
if !copy.equal?(child)
|
|
122
120
|
children = @children.dup
|
|
123
121
|
children[index] = copy
|
|
@@ -129,14 +127,14 @@ module Hamster
|
|
|
129
127
|
end
|
|
130
128
|
|
|
131
129
|
# Returns a replacement instance after removing the specified entry. If empty, returns <tt>nil</tt>
|
|
132
|
-
def
|
|
130
|
+
def delete_at(index = @entries.index { |e| e })
|
|
133
131
|
yield(@entries[index]) if block_given?
|
|
134
132
|
if size > 1
|
|
135
133
|
entries = @entries.dup
|
|
136
134
|
child = @children[index]
|
|
137
135
|
if child
|
|
138
136
|
children = @children.dup
|
|
139
|
-
children[index] = child.
|
|
137
|
+
children[index] = child.delete_at do |entry|
|
|
140
138
|
entries[index] = entry
|
|
141
139
|
end
|
|
142
140
|
else
|
data/lib/hamster/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
require 'hamster/hash'
|
|
4
|
+
|
|
5
|
+
describe Hamster::Hash do
|
|
6
|
+
|
|
7
|
+
describe "#delete" do
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
@original = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "with an existing key" do
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
@result = @original.delete("B")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "preserves the original" do
|
|
20
|
+
@original.should == Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns a copy with the remaining key/value pairs" do
|
|
24
|
+
@result.should == Hamster.hash("A" => "aye", "C" => "see")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "with a non-existing key" do
|
|
30
|
+
|
|
31
|
+
before do
|
|
32
|
+
@result = @original.delete("D")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "preserves the original values" do
|
|
36
|
+
@original.should == Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns self" do
|
|
40
|
+
@result.should equal(@original)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -4,30 +4,34 @@ require 'hamster/hash'
|
|
|
4
4
|
|
|
5
5
|
describe Hamster::Hash do
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[:each, :foreach].each do |method|
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
@hash = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe "with a block (internal iteration)" do
|
|
9
|
+
describe "##{method}" do
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
@hash
|
|
11
|
+
before do
|
|
12
|
+
@hash = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
describe "with a block (internal iteration)" do
|
|
16
|
+
|
|
17
|
+
it "returns nil" do
|
|
18
|
+
@hash.send(method) {}.should be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "yields all key/value pairs" do
|
|
22
|
+
actual_pairs = {}
|
|
23
|
+
@hash.send(method) { |key, value| actual_pairs[key] = value }
|
|
24
|
+
actual_pairs.should == {"A" => "aye", "B" => "bee", "C" => "see"}
|
|
25
|
+
end
|
|
26
|
+
|
|
23
27
|
end
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
describe "with no block" do
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
it "returns self" do
|
|
32
|
+
@hash.send(method).should equal(@hash)
|
|
33
|
+
end
|
|
28
34
|
|
|
29
|
-
it "returns self" do
|
|
30
|
-
@hash.each.should equal(@hash)
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
end
|
|
@@ -4,40 +4,56 @@ require 'hamster/hash'
|
|
|
4
4
|
|
|
5
5
|
describe Hamster::Hash do
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[:remove, :reject, :delete_if].each do |method|
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
@original = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe "with an existing key" do
|
|
9
|
+
describe "##{method}" do
|
|
14
10
|
|
|
15
11
|
before do
|
|
16
|
-
@
|
|
12
|
+
@original = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
describe "when nothing matches" do
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
@result = @original.send(method) { |key, value| false }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns self" do
|
|
22
|
+
@result.should equal(@original)
|
|
23
|
+
end
|
|
22
24
|
|
|
23
|
-
it "returns a copy with the remaining key/value pairs" do
|
|
24
|
-
@result.should == Hamster.hash("A" => "aye", "C" => "see")
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
describe "when only some things match" do
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
describe "with a block" do
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
before do
|
|
32
|
+
@result = @original.send(method) { |key, value| key == "A" && value == "aye" }
|
|
33
|
+
end
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
it "preserves the original" do
|
|
36
|
+
@original.should == Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns a set with the matching values" do
|
|
40
|
+
@result.should == Hamster.hash("B" => "bee", "C" => "see")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "with no block" do
|
|
46
|
+
|
|
47
|
+
before do
|
|
48
|
+
@result = @original.send(method)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "returns self" do
|
|
52
|
+
@result.should equal(@original)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
38
56
|
|
|
39
|
-
it "returns self" do
|
|
40
|
-
@result.should equal(@original)
|
|
41
57
|
end
|
|
42
58
|
|
|
43
59
|
end
|
|
@@ -4,61 +4,65 @@ require 'hamster/list'
|
|
|
4
4
|
|
|
5
5
|
describe Hamster::List do
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[:each, :foreach].each do |method|
|
|
8
8
|
|
|
9
|
-
describe "
|
|
9
|
+
describe "##{method}" do
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
|
13
|
-
end
|
|
11
|
+
describe "doesn't run out of stack space on a really big" do
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
it "stream" do
|
|
14
|
+
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
|
15
|
+
end
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
it "list" do
|
|
18
|
+
@list = (0...STACK_OVERFLOW_DEPTH).reduce(Hamster.list) { |list, i| list.cons(i) }
|
|
19
|
+
end
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
after do
|
|
22
|
+
@list.send(method) { }
|
|
23
|
+
end
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
[],
|
|
27
|
-
["A"],
|
|
28
|
-
["A", "B", "C"],
|
|
29
|
-
].each do |values|
|
|
25
|
+
end
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
[
|
|
28
|
+
[],
|
|
29
|
+
["A"],
|
|
30
|
+
["A", "B", "C"],
|
|
31
|
+
].each do |values|
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
@original = Hamster.list(*values)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe "with a block" do
|
|
33
|
+
describe "on #{values.inspect}" do
|
|
38
34
|
|
|
39
35
|
before do
|
|
40
|
-
@
|
|
41
|
-
@result = @original.each { |value| @items << value }
|
|
36
|
+
@original = Hamster.list(*values)
|
|
42
37
|
end
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
@items.should == values
|
|
46
|
-
end
|
|
39
|
+
describe "with a block" do
|
|
47
40
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
before do
|
|
42
|
+
@items = []
|
|
43
|
+
@result = @original.send(method) { |value| @items << value }
|
|
44
|
+
end
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
it "iterates over the items in order" do
|
|
47
|
+
@items.should == values
|
|
48
|
+
end
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
it "returns nil" do
|
|
51
|
+
@result.should be_nil
|
|
52
|
+
end
|
|
55
53
|
|
|
56
|
-
before do
|
|
57
|
-
@result = @original.each
|
|
58
54
|
end
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
describe "without a block" do
|
|
57
|
+
|
|
58
|
+
before do
|
|
59
|
+
@result = @original.send(method)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "returns self" do
|
|
63
|
+
@result.should equal(@original)
|
|
64
|
+
end
|
|
65
|
+
|
|
62
66
|
end
|
|
63
67
|
|
|
64
68
|
end
|
|
@@ -16,16 +16,14 @@ describe Hamster::List do
|
|
|
16
16
|
|
|
17
17
|
before do
|
|
18
18
|
@original = Hamster.list(*values)
|
|
19
|
-
|
|
20
|
-
@result = @original.init
|
|
21
|
-
end
|
|
19
|
+
@result = @original.init
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
it "preserves the original" do
|
|
25
23
|
@original.should == Hamster.list(*values)
|
|
26
24
|
end
|
|
27
25
|
|
|
28
|
-
it "returns #{expected.inspect}" do
|
|
26
|
+
it "returns the list without the last element: #{expected.inspect}" do
|
|
29
27
|
@result.should == Hamster.list(*expected)
|
|
30
28
|
end
|
|
31
29
|
|
|
@@ -6,9 +6,25 @@ describe Hamster::List do
|
|
|
6
6
|
|
|
7
7
|
describe "#last" do
|
|
8
8
|
|
|
9
|
+
describe "doesn't run out of stack space on a really big" do
|
|
10
|
+
|
|
11
|
+
it "stream" do
|
|
12
|
+
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "list" do
|
|
16
|
+
@list = (0...STACK_OVERFLOW_DEPTH).reduce(Hamster.list) { |list, i| list.cons(i) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
after do
|
|
20
|
+
@list.last
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
9
25
|
[
|
|
10
26
|
[[], nil],
|
|
11
|
-
[["A"],
|
|
27
|
+
[["A"], "A"],
|
|
12
28
|
[["A", "B", "C"], "C"],
|
|
13
29
|
].each do |values, expected|
|
|
14
30
|
|
|
@@ -16,13 +32,11 @@ describe Hamster::List do
|
|
|
16
32
|
|
|
17
33
|
before do
|
|
18
34
|
original = Hamster.list(*values)
|
|
19
|
-
|
|
20
|
-
@result = original.last
|
|
21
|
-
end
|
|
35
|
+
@result = original.last
|
|
22
36
|
end
|
|
23
37
|
|
|
24
38
|
it "returns #{expected.inspect}" do
|
|
25
|
-
@result.should ==
|
|
39
|
+
@result.should == expected
|
|
26
40
|
end
|
|
27
41
|
|
|
28
42
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
require 'hamster/list'
|
|
4
|
+
|
|
5
|
+
describe Hamster::List do
|
|
6
|
+
|
|
7
|
+
describe "#product" do
|
|
8
|
+
|
|
9
|
+
describe "doesn't run out of stack space on a really big" do
|
|
10
|
+
|
|
11
|
+
it "stream" do
|
|
12
|
+
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "list" do
|
|
16
|
+
@list = (0...STACK_OVERFLOW_DEPTH).reduce(Hamster.list) { |list, i| list.cons(i) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
after do
|
|
20
|
+
@list.product
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
[
|
|
26
|
+
[[], 1],
|
|
27
|
+
[[2], 2],
|
|
28
|
+
[[1, 3, 5, 7, 11], 1155],
|
|
29
|
+
].each do |values, expected|
|
|
30
|
+
|
|
31
|
+
describe "on #{values.inspect}" do
|
|
32
|
+
|
|
33
|
+
before do
|
|
34
|
+
original = Hamster.list(*values)
|
|
35
|
+
@result = original.product
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "returns #{expected.inspect}" do
|
|
39
|
+
@result.should == expected
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
require 'hamster/list'
|
|
4
|
+
|
|
5
|
+
describe Hamster::List do
|
|
6
|
+
|
|
7
|
+
describe "#sum" do
|
|
8
|
+
|
|
9
|
+
describe "doesn't run out of stack space on a really big" do
|
|
10
|
+
|
|
11
|
+
it "stream" do
|
|
12
|
+
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "list" do
|
|
16
|
+
@list = (0...STACK_OVERFLOW_DEPTH).reduce(Hamster.list) { |list, i| list.cons(i) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
after do
|
|
20
|
+
@list.sum
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
[
|
|
26
|
+
[[], 0],
|
|
27
|
+
[[2], 2],
|
|
28
|
+
[[1, 3, 5, 7, 11], 27],
|
|
29
|
+
].each do |values, expected|
|
|
30
|
+
|
|
31
|
+
describe "on #{values.inspect}" do
|
|
32
|
+
|
|
33
|
+
before do
|
|
34
|
+
original = Hamster.list(*values)
|
|
35
|
+
@result = original.sum
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "returns #{expected.inspect}" do
|
|
39
|
+
@result.should == expected
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
require 'hamster/set'
|
|
4
|
+
|
|
5
|
+
describe Hamster::Set do
|
|
6
|
+
|
|
7
|
+
describe "#delete" do
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
@original = Hamster.set("A", "B", "C")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "with an existing value" do
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
@result = @original.delete("B")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "preserves the original" do
|
|
20
|
+
@original.should == Hamster.set("A", "B", "C")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns a copy with the remaining of values" do
|
|
24
|
+
@result.should == Hamster.set("A", "C")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "with a non-existing value" do
|
|
30
|
+
|
|
31
|
+
before do
|
|
32
|
+
@result = @original.delete("D")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "preserves the original values" do
|
|
36
|
+
@original.should == Hamster.set("A", "B", "C")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns self" do
|
|
40
|
+
@result.should equal(@original)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -5,30 +5,34 @@ require 'hamster/set'
|
|
|
5
5
|
|
|
6
6
|
describe Hamster::Set do
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
[:each, :foreach].each do |method|
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
@set = Hamster.set("A", "B", "C")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe "with a block (internal iteration)" do
|
|
10
|
+
describe "##{method}" do
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
@set
|
|
12
|
+
before do
|
|
13
|
+
@set = Hamster.set("A", "B", "C")
|
|
18
14
|
end
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
describe "with a block (internal iteration)" do
|
|
17
|
+
|
|
18
|
+
it "returns nil" do
|
|
19
|
+
@set.send(method) {}.should be_nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "yields all values" do
|
|
23
|
+
actual_values = Set[]
|
|
24
|
+
@set.send(method) { |value| actual_values << value }
|
|
25
|
+
actual_values.should == Set["A", "B", "C"]
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
end
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
describe "with no block" do
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
it "returns self" do
|
|
33
|
+
@set.send(method).should equal(@set)
|
|
34
|
+
end
|
|
29
35
|
|
|
30
|
-
it "returns self" do
|
|
31
|
-
@set.each.should equal(@set)
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
end
|
|
@@ -4,40 +4,56 @@ require 'hamster/set'
|
|
|
4
4
|
|
|
5
5
|
describe Hamster::Set do
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[:remove, :reject, :delete_if].each do |method|
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
@original = Hamster.set("A", "B", "C")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe "with an existing value" do
|
|
9
|
+
describe "##{method}" do
|
|
14
10
|
|
|
15
11
|
before do
|
|
16
|
-
@
|
|
12
|
+
@original = Hamster.set("A", "B", "C")
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
describe "when nothing matches" do
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
@result = @original.send(method) { |item| false }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns self" do
|
|
22
|
+
@result.should equal(@original)
|
|
23
|
+
end
|
|
22
24
|
|
|
23
|
-
it "returns a copy with the remaining of values" do
|
|
24
|
-
@result.should == Hamster.set("A", "C")
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
describe "when only some things match" do
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
describe "with a block" do
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
before do
|
|
32
|
+
@result = @original.send(method) { |item| item == "A" }
|
|
33
|
+
end
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
it "preserves the original" do
|
|
36
|
+
@original.should == Hamster.set("A", "B", "C")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns a set with the matching values" do
|
|
40
|
+
@result.should == Hamster.set("B", "C")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "with no block" do
|
|
46
|
+
|
|
47
|
+
before do
|
|
48
|
+
@result = @original.send(method)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "returns self" do
|
|
52
|
+
@result.should equal(@original)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
38
56
|
|
|
39
|
-
it "returns self" do
|
|
40
|
-
@result.should equal(@original)
|
|
41
57
|
end
|
|
42
58
|
|
|
43
59
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hamster
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.23
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Simon Harris
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2010-01-
|
|
12
|
+
date: 2010-01-11 00:00:00 +11:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -50,6 +50,7 @@ files:
|
|
|
50
50
|
- spec/hamster/hash/any_spec.rb
|
|
51
51
|
- spec/hamster/hash/construction_spec.rb
|
|
52
52
|
- spec/hamster/hash/copying_spec.rb
|
|
53
|
+
- spec/hamster/hash/delete_spec.rb
|
|
53
54
|
- spec/hamster/hash/each_spec.rb
|
|
54
55
|
- spec/hamster/hash/empty_spec.rb
|
|
55
56
|
- spec/hamster/hash/eql_spec.rb
|
|
@@ -60,7 +61,6 @@ files:
|
|
|
60
61
|
- spec/hamster/hash/none_spec.rb
|
|
61
62
|
- spec/hamster/hash/put_spec.rb
|
|
62
63
|
- spec/hamster/hash/reduce_spec.rb
|
|
63
|
-
- spec/hamster/hash/reject_spec.rb
|
|
64
64
|
- spec/hamster/hash/remove_spec.rb
|
|
65
65
|
- spec/hamster/hash/size_spec.rb
|
|
66
66
|
- spec/hamster/list/all_spec.rb
|
|
@@ -96,13 +96,15 @@ files:
|
|
|
96
96
|
- spec/hamster/list/none_spec.rb
|
|
97
97
|
- spec/hamster/list/one_spec.rb
|
|
98
98
|
- spec/hamster/list/partition_spec.rb
|
|
99
|
+
- spec/hamster/list/product_spec.rb
|
|
99
100
|
- spec/hamster/list/reduce_spec.rb
|
|
100
|
-
- spec/hamster/list/
|
|
101
|
+
- spec/hamster/list/remove_spec.rb
|
|
101
102
|
- spec/hamster/list/reverse_spec.rb
|
|
102
103
|
- spec/hamster/list/size_spec.rb
|
|
103
104
|
- spec/hamster/list/sorting_spec.rb
|
|
104
105
|
- spec/hamster/list/span_spec.rb
|
|
105
106
|
- spec/hamster/list/split_at_spec.rb
|
|
107
|
+
- spec/hamster/list/sum_spec.rb
|
|
106
108
|
- spec/hamster/list/tail_spec.rb
|
|
107
109
|
- spec/hamster/list/take_spec.rb
|
|
108
110
|
- spec/hamster/list/take_while_spec.rb
|
|
@@ -118,6 +120,7 @@ files:
|
|
|
118
120
|
- spec/hamster/set/construction_spec.rb
|
|
119
121
|
- spec/hamster/set/copying_spec.rb
|
|
120
122
|
- spec/hamster/set/count_spec.rb
|
|
123
|
+
- spec/hamster/set/delete_spec.rb
|
|
121
124
|
- spec/hamster/set/each_spec.rb
|
|
122
125
|
- spec/hamster/set/empty_spec.rb
|
|
123
126
|
- spec/hamster/set/eql_spec.rb
|
|
@@ -134,7 +137,6 @@ files:
|
|
|
134
137
|
- spec/hamster/set/none_spec.rb
|
|
135
138
|
- spec/hamster/set/partition_spec.rb
|
|
136
139
|
- spec/hamster/set/reduce_spec.rb
|
|
137
|
-
- spec/hamster/set/reject_spec.rb
|
|
138
140
|
- spec/hamster/set/remove_spec.rb
|
|
139
141
|
- spec/hamster/set/size_spec.rb
|
|
140
142
|
- spec/hamster/set/sorting_spec.rb
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
-
|
|
3
|
-
require 'hamster/hash'
|
|
4
|
-
|
|
5
|
-
describe Hamster::Hash do
|
|
6
|
-
|
|
7
|
-
[:reject, :delete_if].each do |method|
|
|
8
|
-
|
|
9
|
-
describe "##{method}" do
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
@original = Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
describe "when nothing matches" do
|
|
16
|
-
|
|
17
|
-
before do
|
|
18
|
-
@result = @original.send(method) { |key, value| false }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "returns self" do
|
|
22
|
-
@result.should equal(@original)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe "when only some things match" do
|
|
28
|
-
|
|
29
|
-
describe "with a block" do
|
|
30
|
-
|
|
31
|
-
before do
|
|
32
|
-
@result = @original.send(method) { |key, value| key == "A" && value == "aye" }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "preserves the original" do
|
|
36
|
-
@original.should == Hamster.hash("A" => "aye", "B" => "bee", "C" => "see")
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "returns a set with the matching values" do
|
|
40
|
-
@result.should == Hamster.hash("B" => "bee", "C" => "see")
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
describe "with no block" do
|
|
46
|
-
|
|
47
|
-
before do
|
|
48
|
-
@result = @original.send(method)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "returns self" do
|
|
52
|
-
@result.should equal(@original)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
end
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
-
|
|
3
|
-
require 'hamster/set'
|
|
4
|
-
|
|
5
|
-
describe Hamster::Set do
|
|
6
|
-
|
|
7
|
-
[:reject, :delete_if].each do |method|
|
|
8
|
-
|
|
9
|
-
describe "##{method}" do
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
@original = Hamster.set("A", "B", "C")
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
describe "when nothing matches" do
|
|
16
|
-
|
|
17
|
-
before do
|
|
18
|
-
@result = @original.send(method) { |item| false }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "returns self" do
|
|
22
|
-
@result.should equal(@original)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe "when only some things match" do
|
|
28
|
-
|
|
29
|
-
describe "with a block" do
|
|
30
|
-
|
|
31
|
-
before do
|
|
32
|
-
@result = @original.send(method) { |item| item == "A" }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "preserves the original" do
|
|
36
|
-
@original.should == Hamster.set("A", "B", "C")
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "returns a set with the matching values" do
|
|
40
|
-
@result.should == Hamster.set("B", "C")
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
describe "with no block" do
|
|
46
|
-
|
|
47
|
-
before do
|
|
48
|
-
@result = @original.send(method)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "returns self" do
|
|
52
|
-
@result.should equal(@original)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
end
|