hamster 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +13 -0
- data/README.rdoc +7 -2
- data/lib/hamster/hash.rb +4 -0
- data/lib/hamster/list.rb +13 -4
- data/lib/hamster/set.rb +15 -1
- data/lib/hamster/trie.rb +1 -1
- data/lib/hamster/version.rb +1 -1
- data/spec/hamster/hash/inspect_spec.rb +32 -0
- data/spec/hamster/list/group_by_spec.rb +73 -0
- data/spec/hamster/list/to_ary_spec.rb +14 -7
- data/spec/hamster/set/group_by_spec.rb +61 -0
- data/spec/hamster/set/inspect_spec.rb +1 -17
- data/spec/hamster/set/one_spec.rb +77 -0
- data/spec/hamster/tuple/to_ary_spec.rb +16 -3
- metadata +6 -2
data/History.rdoc
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
=== 0.2.3 / 2010-01-18
|
2
|
+
|
3
|
+
* Implement Set#group_by.
|
4
|
+
|
5
|
+
* Implement List#group_by.
|
6
|
+
|
7
|
+
* Implement Hash#inspect.
|
8
|
+
|
9
|
+
* Tuples can now be implicitly converted to args and variables via #to_ary, meaning you can do:
|
10
|
+
|
11
|
+
integers = Hamster.iterate(1, &:succ)
|
12
|
+
odds, evens = integers.partition(&:odd?)
|
13
|
+
|
1
14
|
=== 0.2.2 / 2010-01-15
|
2
15
|
|
3
16
|
* Implement List#flatten.
|
data/README.rdoc
CHANGED
@@ -128,13 +128,18 @@ Besides <tt>Hamster.list</tt> there are other ways to construct lists:
|
|
128
128
|
|
129
129
|
<tt>Hamster.interval(from, to)</tt> (aliased as <tt>.range</tt>) creates a lazy list equivalent to a list containing all the values between <tt>from</tt> and <tt>to</tt> without actually creating a list that big.
|
130
130
|
|
131
|
-
<tt>Hamster.stream { ... }</tt> allows you to creates infinite lists. Each time a new value is required, the supplied block is called.
|
131
|
+
<tt>Hamster.stream { ... }</tt> allows you to creates infinite lists. Each time a new value is required, the supplied block is called. For example, to generate a list of integers you could do:
|
132
|
+
|
133
|
+
count = 1
|
134
|
+
integers = Hamster.stream { count += 1 }
|
132
135
|
|
133
136
|
<tt>Hamster.repeat(x)</tt> creates an infinite list with x the value for every element.
|
134
137
|
|
135
138
|
<tt>Hamster.replicate(n, x)</tt> creates a list of size n with x the value for every element.
|
136
139
|
|
137
|
-
<tt>Hamster.iterate(x) { ... }</tt> creates an infinite list where the first item is calculated by applying the block on the initial argument, the second item by applying the function on the previous result and so on.
|
140
|
+
<tt>Hamster.iterate(x) { ... }</tt> creates an infinite list where the first item is calculated by applying the block on the initial argument, the second item by applying the function on the previous result and so on. For example, a simpler way to generate a list of integers would be:
|
141
|
+
|
142
|
+
integers = Hamster.iterate(1, &:succ)
|
138
143
|
|
139
144
|
You also get <tt>Enumerable#to_list</tt> so you can slowly transition from built-in collection classes to Hamster.
|
140
145
|
|
data/lib/hamster/hash.rb
CHANGED
@@ -132,6 +132,10 @@ module Hamster
|
|
132
132
|
def_delegator :self, :dup, :nub
|
133
133
|
def_delegator :self, :dup, :remove_duplicates
|
134
134
|
|
135
|
+
def inspect
|
136
|
+
"{#{reduce([]) { |memo, key, value| memo << "#{key.inspect} => #{value.inspect}"}.join(", ")}}"
|
137
|
+
end
|
138
|
+
|
135
139
|
end
|
136
140
|
|
137
141
|
end
|
data/lib/hamster/list.rb
CHANGED
@@ -2,6 +2,7 @@ require 'forwardable'
|
|
2
2
|
require 'monitor'
|
3
3
|
|
4
4
|
require 'hamster/tuple'
|
5
|
+
require 'hamster/hash'
|
5
6
|
require 'hamster/set'
|
6
7
|
|
7
8
|
module Hamster
|
@@ -43,6 +44,10 @@ module Hamster
|
|
43
44
|
|
44
45
|
extend Forwardable
|
45
46
|
|
47
|
+
Undefined = Object.new
|
48
|
+
|
49
|
+
CADR = /^c([ad]+)r$/
|
50
|
+
|
46
51
|
def_delegator :self, :head, :first
|
47
52
|
|
48
53
|
def_delegator :self, :empty?, :null?
|
@@ -440,6 +445,14 @@ module Hamster
|
|
440
445
|
end
|
441
446
|
end
|
442
447
|
|
448
|
+
def group_by(&block)
|
449
|
+
return group_by { |item| item } unless block_given?
|
450
|
+
reduce(Hamster::Hash.new) do |hash, item|
|
451
|
+
key = yield(item)
|
452
|
+
hash.put(key, (hash.get(key) || EmptyList).cons(item))
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
443
456
|
def eql?(other)
|
444
457
|
# return true if other.equal?(self)
|
445
458
|
# return false unless other.is_a?(List)
|
@@ -484,10 +497,6 @@ module Hamster
|
|
484
497
|
|
485
498
|
private
|
486
499
|
|
487
|
-
Undefined = Object.new
|
488
|
-
|
489
|
-
CADR = /^c([ad]+)r$/
|
490
|
-
|
491
500
|
def method_missing(name, *args, &block)
|
492
501
|
if CADR === name
|
493
502
|
accessor($1)
|
data/lib/hamster/set.rb
CHANGED
@@ -7,7 +7,7 @@ require 'hamster/list'
|
|
7
7
|
module Hamster
|
8
8
|
|
9
9
|
def self.set(*items)
|
10
|
-
items.reduce(
|
10
|
+
items.reduce(EmptySet) { |set, item| set.add(item) }
|
11
11
|
end
|
12
12
|
|
13
13
|
class Set
|
@@ -116,6 +116,10 @@ module Hamster
|
|
116
116
|
true
|
117
117
|
end
|
118
118
|
|
119
|
+
def one?
|
120
|
+
return one? { |item| item } unless block_given?
|
121
|
+
end
|
122
|
+
|
119
123
|
def find
|
120
124
|
return nil unless block_given?
|
121
125
|
each { |item| return item if yield(item) }
|
@@ -165,6 +169,14 @@ module Hamster
|
|
165
169
|
remove(&:nil?)
|
166
170
|
end
|
167
171
|
|
172
|
+
def group_by(&block)
|
173
|
+
return group_by { |item| item } unless block_given?
|
174
|
+
reduce(Hamster::Hash.new) do |hash, item|
|
175
|
+
key = yield(item)
|
176
|
+
hash.put(key, (hash.get(key) || EmptySet).add(item))
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
168
180
|
def eql?(other)
|
169
181
|
other.is_a?(self.class) && @trie.eql?(other.instance_eval{@trie})
|
170
182
|
end
|
@@ -194,4 +206,6 @@ module Hamster
|
|
194
206
|
|
195
207
|
end
|
196
208
|
|
209
|
+
EmptySet = Set.new
|
210
|
+
|
197
211
|
end
|
data/lib/hamster/trie.rb
CHANGED
@@ -91,7 +91,7 @@ module Hamster
|
|
91
91
|
|
92
92
|
# Returns <tt>true</tt> if . <tt>eql?</tt> is synonymous with <tt>==</tt>
|
93
93
|
def eql?(other)
|
94
|
-
return true if other.equal?(self)
|
94
|
+
# return true if other.equal?(self)
|
95
95
|
return false unless other.is_a?(self.class) && other.size == size
|
96
96
|
each do |entry|
|
97
97
|
return false unless other.include?(entry.key, entry.value)
|
data/lib/hamster/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'hamster/hash'
|
4
|
+
|
5
|
+
describe Hamster::Hash do
|
6
|
+
|
7
|
+
describe "#inspect" do
|
8
|
+
|
9
|
+
[
|
10
|
+
[[], "{}"],
|
11
|
+
[["A" => "aye"], "{\"A\" => \"aye\"}"],
|
12
|
+
[[1 => :one, 2 => :two, 3 => :three], "{1 => :one, 2 => :two, 3 => :three}"]
|
13
|
+
].each do |values, expected|
|
14
|
+
|
15
|
+
describe "on #{values.inspect}" do
|
16
|
+
|
17
|
+
before do
|
18
|
+
original = Hamster.hash(*values)
|
19
|
+
@result = original.inspect
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns #{expected.inspect}" do
|
23
|
+
@result.should == expected
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'hamster/list'
|
4
|
+
|
5
|
+
describe Hamster::List do
|
6
|
+
|
7
|
+
describe "#group_by" do
|
8
|
+
|
9
|
+
describe "on a really big list" do
|
10
|
+
|
11
|
+
before do
|
12
|
+
@list = Hamster.interval(0, STACK_OVERFLOW_DEPTH)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't run out of stack" do
|
16
|
+
lambda { @list.group_by }.should_not raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "with a block" do
|
22
|
+
|
23
|
+
[
|
24
|
+
[[], []],
|
25
|
+
[[1], [true => Hamster.list(1)]],
|
26
|
+
[[1, 2, 3, 4], [true => Hamster.list(3, 1), false => Hamster.list(4, 2)]],
|
27
|
+
].each do |values, expected|
|
28
|
+
|
29
|
+
describe "on #{values.inspect}" do
|
30
|
+
|
31
|
+
before do
|
32
|
+
original = Hamster.list(*values)
|
33
|
+
@result = original.group_by(&:odd?)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns #{expected.inspect}" do
|
37
|
+
@result.should == Hamster.hash(*expected)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "without a block" do
|
47
|
+
|
48
|
+
[
|
49
|
+
[[], []],
|
50
|
+
[[1], [1 => Hamster.list(1)]],
|
51
|
+
[[1, 2, 3, 4], [1 => Hamster.list(1), 2 => Hamster.list(2), 3 => Hamster.list(3), 4 => Hamster.list(4)]],
|
52
|
+
].each do |values, expected|
|
53
|
+
|
54
|
+
describe "on #{values.inspect}" do
|
55
|
+
|
56
|
+
before do
|
57
|
+
original = Hamster.list(*values)
|
58
|
+
@result = original.group_by
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns #{expected.inspect}" do
|
62
|
+
@result.should == Hamster.hash(*expected)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -21,20 +21,27 @@ describe Hamster::List do
|
|
21
21
|
describe "enables implicit conversion to" do
|
22
22
|
|
23
23
|
before do
|
24
|
-
@list = Hamster.list("A", "B", "C")
|
24
|
+
@list = Hamster.list("A", "B", "C", "D")
|
25
25
|
end
|
26
26
|
|
27
|
-
it "
|
28
|
-
|
29
|
-
|
27
|
+
it "block parameters" do
|
28
|
+
def func(&block)
|
29
|
+
yield(@list)
|
30
|
+
end
|
31
|
+
func do |a, b, *c|
|
32
|
+
a.should == "A"
|
33
|
+
b.should == "B"
|
34
|
+
c.should == ["C", "D"]
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
|
-
it "
|
33
|
-
|
38
|
+
it "method arguments" do
|
39
|
+
def func(a, b, *c)
|
34
40
|
a.should == "A"
|
35
41
|
b.should == "B"
|
36
|
-
c.should == "C"
|
42
|
+
c.should == ["C", "D"]
|
37
43
|
end
|
44
|
+
func(*@list)
|
38
45
|
end
|
39
46
|
|
40
47
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'hamster/set'
|
4
|
+
|
5
|
+
describe Hamster::Set do
|
6
|
+
|
7
|
+
describe "#group_by" do
|
8
|
+
|
9
|
+
describe "with a block" do
|
10
|
+
|
11
|
+
[
|
12
|
+
[[], []],
|
13
|
+
[[1], [true => Hamster.set(1)]],
|
14
|
+
[[1, 2, 3, 4], [true => Hamster.set(3, 1), false => Hamster.set(4, 2)]],
|
15
|
+
].each do |values, expected|
|
16
|
+
|
17
|
+
describe "on #{values.inspect}" do
|
18
|
+
|
19
|
+
before do
|
20
|
+
original = Hamster.set(*values)
|
21
|
+
@result = original.group_by(&:odd?)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns #{expected.inspect}" do
|
25
|
+
@result.should == Hamster.hash(*expected)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "without a block" do
|
35
|
+
|
36
|
+
[
|
37
|
+
[[], []],
|
38
|
+
[[1], [1 => Hamster.set(1)]],
|
39
|
+
[[1, 2, 3, 4], [1 => Hamster.set(1), 2 => Hamster.set(2), 3 => Hamster.set(3), 4 => Hamster.set(4)]],
|
40
|
+
].each do |values, expected|
|
41
|
+
|
42
|
+
describe "on #{values.inspect}" do
|
43
|
+
|
44
|
+
before do
|
45
|
+
original = Hamster.set(*values)
|
46
|
+
@result = original.group_by
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns #{expected.inspect}" do
|
50
|
+
@result.should == Hamster.hash(*expected)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -2,26 +2,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
|
3
3
|
require 'hamster/set'
|
4
4
|
|
5
|
-
describe Hamster::
|
5
|
+
describe Hamster::Set do
|
6
6
|
|
7
7
|
describe "#inspect" 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.inspect
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
9
|
[
|
26
10
|
[[], "{}"],
|
27
11
|
[["A"], "{\"A\"}"],
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'hamster/set'
|
4
|
+
|
5
|
+
describe Hamster::Set do
|
6
|
+
|
7
|
+
describe "#one?" do
|
8
|
+
|
9
|
+
describe "when empty" do
|
10
|
+
|
11
|
+
before do
|
12
|
+
@set = Hamster.set
|
13
|
+
end
|
14
|
+
|
15
|
+
it "with a block returns false" do
|
16
|
+
pending do
|
17
|
+
@set.one? {}.should == false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "with no block returns false" do
|
22
|
+
pending do
|
23
|
+
@set.one?.should == false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when not empty" do
|
30
|
+
|
31
|
+
describe "with a block" do
|
32
|
+
|
33
|
+
before do
|
34
|
+
@set = Hamster.set("A", "B", "C")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns false if the block returns true more than once" do
|
38
|
+
pending do
|
39
|
+
@set.one? { |item| true }.should == false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns fale if the block never returns true" do
|
44
|
+
pending do
|
45
|
+
@set.one? { |item| false }.should == false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns true if the block only returns true once" do
|
50
|
+
pending do
|
51
|
+
@set.one? { |item| item == "A" }.should == true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "with no block" do
|
58
|
+
|
59
|
+
it "returns false if more than one value is truthy" do
|
60
|
+
pending do
|
61
|
+
Hamster.set(nil, true, "A").one?.should == false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns true if only one value is truthy" do
|
66
|
+
pending do
|
67
|
+
Hamster.set(nil, true, false).one?.should == true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -9,14 +9,27 @@ describe Hamster::Tuple do
|
|
9
9
|
describe "enables implicit conversion to" do
|
10
10
|
|
11
11
|
before do
|
12
|
-
@tuple = Hamster::Tuple.new("A", "B")
|
12
|
+
@tuple = Hamster::Tuple.new("A", "B", "C", "D")
|
13
13
|
end
|
14
14
|
|
15
|
-
it "
|
16
|
-
|
15
|
+
it "block parameters" do
|
16
|
+
def func(&block)
|
17
|
+
yield(@tuple)
|
18
|
+
end
|
19
|
+
func do |a, b, *c|
|
20
|
+
a.should == "A"
|
21
|
+
b.should == "B"
|
22
|
+
c.should == ["C", "D"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "method arguments" do
|
27
|
+
def func(a, b, *c)
|
17
28
|
a.should == "A"
|
18
29
|
b.should == "B"
|
30
|
+
c.should == ["C", "D"]
|
19
31
|
end
|
32
|
+
func(*@tuple)
|
20
33
|
end
|
21
34
|
|
22
35
|
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.2.
|
4
|
+
version: 0.2.3
|
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-18 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- spec/hamster/hash/filter_spec.rb
|
59
59
|
- spec/hamster/hash/get_spec.rb
|
60
60
|
- spec/hamster/hash/has_key_spec.rb
|
61
|
+
- spec/hamster/hash/inspect_spec.rb
|
61
62
|
- spec/hamster/hash/map_spec.rb
|
62
63
|
- spec/hamster/hash/none_spec.rb
|
63
64
|
- spec/hamster/hash/put_spec.rb
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- spec/hamster/list/find_spec.rb
|
90
91
|
- spec/hamster/list/flatten_spec.rb
|
91
92
|
- spec/hamster/list/grep_spec.rb
|
93
|
+
- spec/hamster/list/group_by_spec.rb
|
92
94
|
- spec/hamster/list/head_spec.rb
|
93
95
|
- spec/hamster/list/include_spec.rb
|
94
96
|
- spec/hamster/list/init_spec.rb
|
@@ -136,6 +138,7 @@ files:
|
|
136
138
|
- spec/hamster/set/filter_spec.rb
|
137
139
|
- spec/hamster/set/find_spec.rb
|
138
140
|
- spec/hamster/set/grep_spec.rb
|
141
|
+
- spec/hamster/set/group_by_spec.rb
|
139
142
|
- spec/hamster/set/head_spec.rb
|
140
143
|
- spec/hamster/set/include_spec.rb
|
141
144
|
- spec/hamster/set/inspect_spec.rb
|
@@ -144,6 +147,7 @@ files:
|
|
144
147
|
- spec/hamster/set/maximum_spec.rb
|
145
148
|
- spec/hamster/set/minimum_spec.rb
|
146
149
|
- spec/hamster/set/none_spec.rb
|
150
|
+
- spec/hamster/set/one_spec.rb
|
147
151
|
- spec/hamster/set/partition_spec.rb
|
148
152
|
- spec/hamster/set/product_spec.rb
|
149
153
|
- spec/hamster/set/reduce_spec.rb
|