hamsterdam 1.0.5 → 1.0.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.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ Hamsterdam v1.0.5
2
+ * Added hamsterdam/clj to allow for optionally using the Clojure PersistentHashMap isntead of a Hamster hash as the backing data structure
3
+
1
4
  Hamsterdam v1.0.5
2
5
  * Setters return the same instance of the object if the value being set is unchanged
3
6
  * Optimized creation of a new struct caused by a setter modification by skipping validation
data/lib/hamsterdam.rb CHANGED
@@ -2,10 +2,67 @@ require 'hamster'
2
2
 
3
3
  module Hamsterdam
4
4
 
5
+ module Hamster
6
+
7
+ def self.hash(*hash)
8
+ ::Hamster.hash(*hash)
9
+ end
10
+
11
+ def self.set(*values)
12
+ ::Hamster.set(*values)
13
+ end
14
+
15
+ def self.list(*values)
16
+ ::Hamster.list(*values)
17
+ end
18
+
19
+ def self.internal_hash_class
20
+ ::Hamster::Hash
21
+ end
22
+
23
+ def self.symbolize_keys(hash)
24
+ hash.reduce(hash) do |memo,k,v|
25
+ if Symbol === k
26
+ memo
27
+ else
28
+ memo.delete(k).put(k.to_sym, v)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
5
34
  def self.Struct(*field_names)
6
35
  Hamsterdam::Struct.define(*field_names)
7
36
  end
8
37
 
38
+ def self.internals=(mod)
39
+ @internal_representation_module = mod
40
+ end
41
+
42
+ def self.internals
43
+ @internal_representation_module
44
+ end
45
+
46
+ def self.hash(*hash)
47
+ internals.hash(*hash)
48
+ end
49
+
50
+ def self.set(*values)
51
+ internals.set(*values)
52
+ end
53
+
54
+ def self.list(*values)
55
+ internals.list(*values)
56
+ end
57
+
58
+ def self.internal_hash_class
59
+ internals.internal_hash_class
60
+ end
61
+
62
+ def self.symbolize_keys(hash)
63
+ internals.symbolize_keys(hash)
64
+ end
65
+
9
66
  class Struct
10
67
  def self.define(*field_names)
11
68
  struct_class = Class.new(Hamsterdam::Struct) do
@@ -23,11 +80,10 @@ module Hamsterdam
23
80
  end
24
81
  end
25
82
  end
26
-
27
83
  end
28
84
 
29
- struct_class.instance_variable_set(:@field_names, Hamster.set(*field_names))
30
- struct_class.instance_variable_set(:@field_names_list, Hamster.list(*field_names))
85
+ struct_class.instance_variable_set(:@field_names, Hamsterdam.set(*field_names))
86
+ struct_class.instance_variable_set(:@field_names_list, Hamsterdam.list(*field_names))
31
87
  class << struct_class
32
88
  def field_names
33
89
  if !@field_names.nil?
@@ -47,9 +103,9 @@ module Hamsterdam
47
103
  struct_class
48
104
  end
49
105
 
50
- def initialize(values=Hamster.hash, validate=true)
106
+ def initialize(values=Hamsterdam.hash, validate=true)
51
107
  if validate
52
- @data = flesh_out(ensure_hamster_hash(values))
108
+ @data = flesh_out(ensure_expected_hash(values))
53
109
  validate_keys(@data)
54
110
  else
55
111
  @data = values
@@ -57,11 +113,11 @@ module Hamsterdam
57
113
  end
58
114
 
59
115
  def merge(values)
60
- self.class.new(@data.merge(ensure_hamster_hash(values)))
116
+ self.class.new(@data.merge(ensure_expected_hash(values)))
61
117
  end
62
118
 
63
119
  def ==(other)
64
- @data == other.to_hamster_hash
120
+ internal_hash == other.internal_hash
65
121
  end
66
122
 
67
123
  def eql?(other)
@@ -72,9 +128,10 @@ module Hamsterdam
72
128
  @data.hash
73
129
  end
74
130
 
75
- def to_hamster_hash
131
+ def internal_hash
76
132
  @data
77
133
  end
134
+ alias_method :to_hamster_hash, :internal_hash
78
135
 
79
136
  def inspect
80
137
  to_s
@@ -82,7 +139,7 @@ module Hamsterdam
82
139
 
83
140
  def to_s
84
141
  name = self.class.name ? self.class.name.split(/::/).last : self.class.to_s
85
- data = to_hamster_hash
142
+ data = internal_hash
86
143
  fields = self.class.field_names_list.map { |fname| "#{fname}: #{data[fname].inspect}" }
87
144
  "<#{([name]+fields).join(" ")}>"
88
145
  end
@@ -90,20 +147,20 @@ module Hamsterdam
90
147
  private
91
148
  def validate_keys(data)
92
149
  valid_keys = self.class.field_names
93
- bad_keys = data.keys - valid_keys
150
+ bad_keys = data.keys - valid_keys.to_a
94
151
  if bad_keys.any?
95
152
  raise "#{self.class.name || "Anonymous Hamsterdam::Struct"} can't be constructed with #{bad_keys.inspect}. Valid keys: #{valid_keys.inspect}"
96
153
  end
97
154
  end
98
155
 
99
- def ensure_hamster_hash(h)
156
+ def ensure_expected_hash(h)
100
157
  case h
101
158
  when Hash
102
- Hamster.hash(h)
103
- when Hamster::Hash
159
+ Hamsterdam.hash(h)
160
+ when Hamsterdam.internal_hash_class
104
161
  h
105
162
  else
106
- raise "Expected Hash or Hamster::Hash. Do not want: #{h.inspect}"
163
+ raise "Expected Hash or #{Hamsterdam.internal_hash_class}. Do not want: #{h.inspect}"
107
164
  end
108
165
  end
109
166
 
@@ -120,13 +177,8 @@ module Hamsterdam
120
177
  end
121
178
 
122
179
  def symbolize_keys(data)
123
- data.reduce(data) do |memo,k,v|
124
- if Symbol === k
125
- memo
126
- else
127
- memo.delete(k).put(k.to_sym, v)
128
- end
129
- end
180
+ Hamsterdam.symbolize_keys(data)
130
181
  end
131
182
  end
132
183
  end
184
+ Hamsterdam.internals = Hamsterdam::Hamster
@@ -0,0 +1,77 @@
1
+
2
+ class Java::ClojureLang::PersistentHashMap
3
+ alias_method :put, :assoc
4
+ alias_method :delete, :without
5
+ alias_method :==, :equals
6
+ end
7
+
8
+ # java_import 'clojure.lang.PersistentList$EmptyList'
9
+ # class EmptyList
10
+ # def inspect
11
+ # to_a.inspect
12
+ # end
13
+ # end
14
+ #
15
+ # class Java::ClojureLang::PersistentList
16
+ # def inspect
17
+ # to_a.inspect
18
+ # end
19
+ # end
20
+ #
21
+ # class Java::ClojureLang::PersistentHashSet
22
+ # def inspect
23
+ # to_set.inspect
24
+ # end
25
+ #
26
+ # def -(other)
27
+ # reject { |e| other.include?(e) }
28
+ # end
29
+ #
30
+ # alias_method :add, :cons
31
+ # end
32
+
33
+ module Hamsterdam
34
+ module Clojure
35
+ def self.hash(h = nil)
36
+ if h.nil?
37
+ Java::ClojureLang::PersistentHashMap::EMPTY
38
+ else
39
+ Java::ClojureLang::PersistentHashMap.create(h)
40
+ end
41
+ end
42
+
43
+ def self.internal_hash_class
44
+ Java::ClojureLang::PersistentHashMap
45
+ end
46
+
47
+ # def self.set(*values)
48
+ # Java::ClojureLang::PersistentHashSet.create(values)
49
+ # end
50
+
51
+ # def self.list(*values)
52
+ # values.reverse.inject(Java::ClojureLang::PersistentList::EMPTY) do |list, value|
53
+ # list.cons(value)
54
+ # end
55
+ # end
56
+
57
+ def self.set(*values)
58
+ ::Hamster.set(*values)
59
+ end
60
+
61
+ def self.list(*values)
62
+ ::Hamster.list(*values)
63
+ end
64
+
65
+ def self.symbolize_keys(hash)
66
+ hash.reduce(hash) do |memo,(k,v)|
67
+ if Symbol === k
68
+ memo
69
+ else
70
+ memo.delete(k).put(k.to_sym, v)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ Hamsterdam.internals = Hamsterdam::Clojure
@@ -1,3 +1,3 @@
1
1
  module Hamsterdam
2
- VERSION = "1.0.5"
2
+ VERSION = "1.0.6"
3
3
  end
@@ -7,6 +7,53 @@ describe "Hamsterdam structures" do
7
7
 
8
8
  let(:struct_class) { define_hamsterdam_struct(:top, :bottom) }
9
9
 
10
+ describe "immutable data structure helpers" do
11
+ describe "#hash" do
12
+ it "provides an empty hash" do
13
+ h = Hamsterdam.hash
14
+ h.should be_empty
15
+ h.class.should == Hamsterdam.internal_hash_class
16
+ h.should == Hamsterdam.hash
17
+ end
18
+
19
+ it "provides a hash populated with passed in key/values" do
20
+ h = Hamsterdam.hash(a: "1", b: "2")
21
+ h[:a].should == "1"
22
+ h[:b].should == "2"
23
+ h.class.should == Hamsterdam.internal_hash_class
24
+ end
25
+ end
26
+
27
+ describe "#set" do
28
+ it "provides an empty set" do
29
+ s = Hamsterdam.set
30
+ s.should be_empty
31
+ end
32
+
33
+ it "provides a set populated with passed values" do
34
+ s = Hamsterdam.set("a", "b", "c", "a")
35
+ s.should_not be_empty
36
+ s.should have(3).entries
37
+ s.should include("a", "b", "c")
38
+ end
39
+ end
40
+
41
+ describe "#list" do
42
+ it "provides an empty list" do
43
+ l = Hamsterdam.list
44
+ l.should be_empty
45
+ end
46
+
47
+ it "provides a list populated with passed values" do
48
+ l = Hamsterdam.list("a", "b", "c", "a")
49
+ l.should_not be_empty
50
+ l.should have(4).items
51
+ l.should include("a", "b", "c")
52
+ l.to_a.should == ["a", "b", "c", "a"]
53
+ end
54
+ end
55
+ end
56
+
10
57
  describe "Struct.define" do
11
58
 
12
59
  it "creates a structure class based on the given fields" do
@@ -16,8 +63,8 @@ describe "Hamsterdam structures" do
16
63
  struct.bottom.should == "all the way down"
17
64
  end
18
65
 
19
- it "can be built with Hamster hashes" do
20
- struct = struct_class.new(Hamster.hash(top: 10, bottom: "low"))
66
+ it "can be built with underlying persistent data structure hashes hashes" do
67
+ struct = struct_class.new(Hamsterdam.hash(top: 10, bottom: "low"))
21
68
  struct.should be
22
69
  struct.top.should == 10
23
70
  struct.bottom.should == "low"
@@ -39,9 +86,9 @@ describe "Hamsterdam structures" do
39
86
  struct.bottom.should be_nil
40
87
  end
41
88
 
42
- it "provides access to the internal data as a Hamster.hash" do
89
+ it "provides access to the internal data as the correct hash type" do
43
90
  s1 = struct_class.new(top: 50, bottom: 75)
44
- s1.to_hamster_hash.should == Hamster.hash(top: 50, bottom: 75)
91
+ s1.internal_hash.should == Hamsterdam.hash(top: 50, bottom: 75)
45
92
  end
46
93
 
47
94
  it "raises helpful error when constructed with invalid objects" do
@@ -98,16 +145,16 @@ describe "Hamsterdam structures" do
98
145
  it "considers equal two structs if one has missing keys, and the other has nil values for those keys" do
99
146
  s1 = struct_class.new(top: 50, bottom: nil)
100
147
  s2 = struct_class.new(top: 50)
101
- #binding.pry
102
- s1.eql?(s2).should == true
148
+ # binding.pry
103
149
  (s1 == s2).should == true
150
+ s1.eql?(s2).should == true
104
151
  s1.should == s2
105
152
  end
106
153
  end
107
154
 
108
- it "uses the same #hash as Hamster::Hash" do
155
+ it "uses the same #hash as the underlying data structure" do
109
156
  s1 = struct_class.new(top: 50, bottom: 75)
110
- s1.hash.should == Hamster.hash(top:50, bottom:75).hash
157
+ s1.hash.should == Hamsterdam.hash(top:50, bottom:75).hash
111
158
  end
112
159
 
113
160
  describe "transformation" do
@@ -141,10 +188,10 @@ describe "Hamsterdam structures" do
141
188
  struct3.bottom.should == "very"
142
189
  end
143
190
 
144
- it "can merge-in Hamster::Hash" do
191
+ it "can merge-in a non-ruby hash" do
145
192
  struct = struct_class.new(top: 10, bottom: 1)
146
193
 
147
- struct2 = struct.merge(Hamster.hash(bottom: "newer", top: "newest"))
194
+ struct2 = struct.merge(Hamsterdam.hash(bottom: "newer", top: "newest"))
148
195
  struct2.top.should == "newest"
149
196
  struct2.bottom.should == "newer"
150
197
 
@@ -211,7 +258,7 @@ describe "Hamsterdam structures" do
211
258
  val.foo.should == 3
212
259
  val.bar.should == 4
213
260
 
214
- val.to_hamster_hash.should == Hamster.hash(foo: 3, bar: 4)
261
+ val.internal_hash.should == Hamsterdam.hash(foo: 3, bar: 4)
215
262
  end
216
263
  end
217
264
  end
data/spec/spec_helper.rb CHANGED
@@ -11,9 +11,14 @@ end
11
11
 
12
12
  #ENV["APP_ENV"] = "rspec"
13
13
 
14
+ require 'pry'
14
15
  require 'hamsterdam'
15
16
 
16
- require 'pry'
17
+ if ENV['clj'] == 'true'
18
+ require "#{PROJECT_ROOT}/spec/jars/clojure-1.5.1.jar"
19
+ require 'hamsterdam/clj'
20
+ end
21
+
17
22
 
18
23
  # Load all support files
19
24
  Dir["#{PROJECT_ROOT}/spec/support/*.rb"].each do |support|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hamsterdam
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-02 00:00:00.000000000 Z
12
+ date: 2013-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hamster
@@ -100,6 +100,7 @@ extra_rdoc_files: []
100
100
  files:
101
101
  - README.md
102
102
  - CHANGELOG
103
+ - lib/hamsterdam/clj.rb
103
104
  - lib/hamsterdam/version.rb
104
105
  - lib/hamsterdam.rb
105
106
  - spec/hamsterdam_spec.rb
@@ -117,12 +118,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
118
  - - ! '>='
118
119
  - !ruby/object:Gem::Version
119
120
  version: '0'
121
+ segments:
122
+ - 0
123
+ hash: 4489320240594326591
120
124
  required_rubygems_version: !ruby/object:Gem::Requirement
121
125
  none: false
122
126
  requirements:
123
127
  - - ! '>='
124
128
  - !ruby/object:Gem::Version
125
129
  version: '0'
130
+ segments:
131
+ - 0
132
+ hash: 4489320240594326591
126
133
  requirements: []
127
134
  rubyforge_project:
128
135
  rubygems_version: 1.8.24