hamsterdam 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
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