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 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(Set.new) { |set, item| set.add(item) }
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)
@@ -1,5 +1,5 @@
1
1
  module Hamster
2
2
 
3
- VERSION = "0.2.2".freeze
3
+ VERSION = "0.2.3".freeze
4
4
 
5
5
  end
@@ -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 "arrays" do
28
- array = *@list
29
- array.should == ["A", "B", "C"]
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 "call parameters" do
33
- [@list].each do |a, b, c|
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::List do
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 "call parameters" do
16
- [@tuple].each do |a, b|
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.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-16 00:00:00 +11:00
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