hamster 0.1.5 → 0.1.6

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.
@@ -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