hamster 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === 0.1.6 / 2009-11-23
2
+
3
+ * First cut at finishing implementation of Hash.
4
+
1
5
  === 0.1.5 / 2009-11-5
2
6
 
3
7
  * Add some examples
@@ -23,7 +23,10 @@ module Hamster
23
23
 
24
24
  # Retrieves the value corresponding to the given key. If not found, returns <tt>nil</tt>.
25
25
  def get(key)
26
- @trie.get(key)
26
+ entry = @trie.get(key)
27
+ if entry
28
+ entry.value
29
+ end
27
30
  end
28
31
 
29
32
  # Returns a copy of <tt>self</tt> with the given value associated with the key.
@@ -34,10 +37,10 @@ module Hamster
34
37
  # Returns a copy of <tt>self</tt> with the given key/value pair removed. If not found, returns <tt>self</tt>.
35
38
  def remove(key)
36
39
  copy = @trie.remove(key)
37
- if copy.equal?(@trie)
38
- self
39
- else
40
+ if !copy.equal?(@trie)
40
41
  self.class.new(copy)
42
+ else
43
+ self
41
44
  end
42
45
  end
43
46
 
@@ -45,7 +48,7 @@ module Hamster
45
48
  # Returns <tt>self</tt>
46
49
  def each
47
50
  block_given? or return enum_for(__method__)
48
- @trie.each { |key, value| yield key, value }
51
+ @trie.each { |entry| yield entry.key, entry.value }
49
52
  self
50
53
  end
51
54
 
@@ -13,7 +13,7 @@ module Hamster
13
13
 
14
14
  # Returns <tt>true</tt> if the set contains no items.
15
15
  def empty?
16
- @trie.size
16
+ @trie.empty?
17
17
  end
18
18
 
19
19
  # Returns <tt>true</tt> if the given item is present in the set.
@@ -33,10 +33,10 @@ module Hamster
33
33
  # Returns a copy of <tt>self</tt> with the given item removed. If not found, returns <tt>self</tt>.
34
34
  def remove(key)
35
35
  copy = @trie.remove(item)
36
- if copy.equal?(@trie)
37
- self
38
- else
36
+ if !copy.equal?(@trie)
39
37
  self.class.new(copy)
38
+ else
39
+ self
40
40
  end
41
41
  end
42
42
 
@@ -44,7 +44,7 @@ module Hamster
44
44
  # Returns <tt>self</tt>
45
45
  def each
46
46
  block_given? or return enum_for(__method__)
47
- @trie.each { |key, value| yield key }
47
+ @trie.each { |entry| yield entry.key }
48
48
  self
49
49
  end
50
50
 
@@ -27,9 +27,9 @@ module Hamster
27
27
 
28
28
  # Calls <tt>block</tt> once for each entry in the trie, passing the key-value pair as parameters.
29
29
  def each
30
- @entries.each { |entry| yield entry.key, entry.value if entry }
30
+ @entries.each { |entry| yield entry if entry }
31
31
  @children.each do |child|
32
- child.each { |key, value| yield key, value } if child
32
+ child.each { |entry| yield entry } if child
33
33
  end
34
34
  end
35
35
 
@@ -37,7 +37,11 @@ module Hamster
37
37
  def put(key, value)
38
38
  index = index_for(key)
39
39
  entry = @entries[index]
40
- if entry && !entry.has_key?(key)
40
+ if !entry || entry.key_eql?(key)
41
+ entries = @entries.dup
42
+ entries[index] = Entry.new(key, value)
43
+ self.class.new(@significant_bits, entries, @children)
44
+ else
41
45
  children = @children.dup
42
46
  child = children[index]
43
47
  children[index] = if child
@@ -46,19 +50,15 @@ module Hamster
46
50
  self.class.new(@significant_bits + 5).put!(key, value)
47
51
  end
48
52
  self.class.new(@significant_bits, @entries, children)
49
- else
50
- entries = @entries.dup
51
- entries[index] = Entry.new(key, value)
52
- self.class.new(@significant_bits, entries, @children)
53
53
  end
54
54
  end
55
55
 
56
- # Retrieves the value corresponding to the given key. If not found, returns <tt>nil</tt>.
56
+ # Retrieves the entry corresponding to the given key. If not found, returns <tt>nil</tt>.
57
57
  def get(key)
58
58
  index = index_for(key)
59
59
  entry = @entries[index]
60
- if entry && entry.has_key?(key)
61
- entry.value
60
+ if entry && entry.key_eql?(key)
61
+ entry
62
62
  else
63
63
  child = @children[index]
64
64
  if child
@@ -67,44 +67,63 @@ module Hamster
67
67
  end
68
68
  end
69
69
 
70
- # Returns a copy of <tt>self</tt> with the given key/value pair removed. If not found, returns <tt>self</tt>.
70
+ # Returns a copy of <tt>self</tt> with the given key (and associated value) removed. If not found, returns <tt>self</tt>.
71
71
  def remove(key)
72
- remove!(key) || self
72
+ xxx(key) || Trie.new(@significant_bits)
73
73
  end
74
74
 
75
75
  # Returns <tt>true</tt> if . <tt>eql?</tt> is synonymous with <tt>==</tt>
76
76
  def eql?(other)
77
- blammo!
77
+ false
78
78
  end
79
79
  alias :== :eql?
80
80
 
81
81
  protected
82
82
 
83
+ # Returns <tt>self</tt> after overwriting the element associated with the specified key.
83
84
  def put!(key, value)
84
85
  @entries[index_for(key)] = Entry.new(key, value)
85
86
  self
86
87
  end
87
-
88
- def remove!(key)
88
+
89
+ # Returns a replacement instance after removing the specified key.
90
+ # If not found, returns <tt>self</tt>.
91
+ # If empty, returns <tt>nil</tt>.
92
+ def xxx(key)
89
93
  index = index_for(key)
90
94
  entry = @entries[index]
91
- if entry && entry.has_key?(key)
92
- if size > 1
93
- entries = @entries.dup
94
- entries[index] = nil
95
- self.class.new(@significant_bits, entries, @children)
96
- end
95
+ if entry && entry.key_eql?(key)
96
+ return remove_at(index)
97
97
  else
98
98
  child = @children[index]
99
99
  if child
100
- copy = child.remove!(key)
100
+ copy = child.xxx(key)
101
101
  if !copy.equal?(child)
102
102
  children = @children.dup
103
103
  children[index] = copy
104
- self.class.new(@significant_bits, @entries, children)
104
+ return self.class.new(@significant_bits, @entries, children)
105
105
  end
106
106
  end
107
107
  end
108
+ self
109
+ end
110
+
111
+ # Returns a replacement instance after removing the specified entry. If empty, returns <tt>nil</tt>
112
+ def remove_at(index = @entries.index { |e| e })
113
+ yield @entries[index] if block_given?
114
+ if size > 1
115
+ entries = @entries.dup
116
+ child = @children[index]
117
+ if child
118
+ children = @children.dup
119
+ children[index] = child.remove_at do |entry|
120
+ entries[index] = entry
121
+ end
122
+ else
123
+ entries[index] = nil
124
+ end
125
+ self.class.new(@significant_bits, entries, children || @children)
126
+ end
108
127
  end
109
128
 
110
129
  private
@@ -122,7 +141,7 @@ module Hamster
122
141
  @value = value
123
142
  end
124
143
 
125
- def has_key?(key)
144
+ def key_eql?(key)
126
145
  @key.eql?(key)
127
146
  end
128
147
 
@@ -1,5 +1,5 @@
1
1
  module Hamster
2
2
 
3
- VERSION = "0.1.5".freeze
3
+ VERSION = "0.1.6".freeze
4
4
 
5
5
  end
@@ -15,6 +15,20 @@ describe Hamster::Hash do
15
15
  end
16
16
  end
17
17
 
18
+ it "is true for two instances with the same key/value pairs" do
19
+ pending do
20
+ a = Hamster::Hash.new.put("a", "Aye").put("b", "Bee").put("c", "See")
21
+ b = Hamster::Hash.new.put("a", "Aye").put("b", "Bee").put("c", "See")
22
+ a.should eql(b)
23
+ end
24
+ end
25
+
26
+ it "is false for two instances with different key/value pairs" do
27
+ a = Hamster::Hash.new.put("a", "Aye").put("b", "Bee").put("c", "See")
28
+ b = Hamster::Hash.new.put("a", "Aye").put("b", "Bee")
29
+ a.should_not eql(b)
30
+ end
31
+
18
32
  end
19
33
 
20
34
  end
@@ -5,7 +5,7 @@ describe Hamster::Hash do
5
5
  describe "#has_key?" do
6
6
 
7
7
  before do
8
- @hash = Hamster::Hash.new.put("A", "aye")
8
+ @hash = Hamster::Hash.new.put("A", "aye").put("NIL", nil)
9
9
  end
10
10
 
11
11
  it "returns true for an existing key" do
@@ -15,6 +15,10 @@ describe Hamster::Hash do
15
15
  it "returns false for a non-existing key" do
16
16
  @hash.has_key?("B").should be_false
17
17
  end
18
+
19
+ it "returns true for a nil value" do
20
+ @hash.has_key?("NIL").should be_true
21
+ end
18
22
 
19
23
  end
20
24
 
@@ -88,6 +88,18 @@ describe Hamster::Hash do
88
88
 
89
89
  end
90
90
 
91
+ describe "with a nil key" do
92
+
93
+ before do
94
+ @hash = Hamster::Hash.new.put(nil, "NIL")
95
+ end
96
+
97
+ it "can locate the key/value pair" do
98
+ @hash.get(nil).should == "NIL"
99
+ end
100
+
101
+ end
102
+
91
103
  end
92
104
 
93
105
  end
@@ -3,6 +3,18 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
3
  describe Hamster::Hash do
4
4
 
5
5
  describe "#remove" do
6
+
7
+ describe "the last key" do
8
+
9
+ before do
10
+ @hash = Hamster::Hash.new.put("A", "aye").remove("A")
11
+ end
12
+
13
+ it "no longer provides access to the removed key" do
14
+ @hash.has_key?("A").should be_false
15
+ end
16
+
17
+ end
6
18
 
7
19
  describe "with an existing key" do
8
20
 
@@ -79,7 +91,7 @@ describe Hamster::Hash do
79
91
 
80
92
  def instance_count
81
93
  ObjectSpace.garbage_collect
82
- ObjectSpace.each_object(Hamster::Hash) {}
94
+ ObjectSpace.each_object(Hamster::Trie) {}
83
95
  end
84
96
 
85
97
  before do
@@ -98,14 +110,6 @@ describe Hamster::Hash do
98
110
  copy.get(@b).should == "bee"
99
111
  end
100
112
 
101
- it "cleans up empty instances" do
102
- pending do
103
- instance_count_before = instance_count
104
- # copy = @original.remove(@b)
105
- instance_count.should == instance_count_before + 1
106
- end
107
- end
108
-
109
113
  end
110
114
 
111
115
  end
@@ -1,4 +1,4 @@
1
- require "spec/rake/spectask"
1
+ require 'spec/rake/spectask'
2
2
 
3
3
  desc "Run specifications"
4
4
  Spec::Rake::SpecTask.new(:spec) do |t|
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.5
4
+ version: 0.1.6
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: 2009-11-07 00:00:00 +11:00
12
+ date: 2009-11-23 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies: []
15
15