veritas 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -4
- data/Gemfile +16 -14
- data/Guardfile +0 -4
- data/README.md +188 -0
- data/Rakefile +2 -2
- data/TODO +0 -16
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/roodi.yml +4 -4
- data/config/site.reek +7 -3
- data/lib/veritas/aggregate.rb +18 -0
- data/lib/veritas/algebra/extension.rb +2 -29
- data/lib/veritas/algebra/projection.rb +2 -29
- data/lib/veritas/algebra/rename/aliases.rb +4 -32
- data/lib/veritas/algebra/rename.rb +2 -29
- data/lib/veritas/algebra/restriction.rb +2 -29
- data/lib/veritas/algebra/summarization.rb +2 -31
- data/lib/veritas/attribute/time.rb +1 -1
- data/lib/veritas/attribute.rb +20 -40
- data/lib/veritas/function/binary.rb +2 -3
- data/lib/veritas/function/connective/negation.rb +1 -1
- data/lib/veritas/function/predicate/enumerable.rb +19 -0
- data/lib/veritas/function/predicate/exclusion.rb +1 -1
- data/lib/veritas/function/predicate/match.rb +1 -1
- data/lib/veritas/function/unary.rb +5 -3
- data/lib/veritas/function.rb +1 -41
- data/lib/veritas/relation/base.rb +2 -29
- data/lib/veritas/relation/empty.rb +30 -2
- data/lib/veritas/relation/header.rb +17 -31
- data/lib/veritas/relation/materialized.rb +0 -12
- data/lib/veritas/relation/operation/limit.rb +2 -29
- data/lib/veritas/relation/operation/offset.rb +2 -29
- data/lib/veritas/relation/operation/order/direction.rb +3 -29
- data/lib/veritas/relation/operation/order/direction_set.rb +18 -34
- data/lib/veritas/relation/operation/order.rb +4 -56
- data/lib/veritas/relation.rb +8 -36
- data/lib/veritas/support/aliasable.rb +20 -7
- data/lib/veritas/support/comparator.rb +81 -0
- data/lib/veritas/support/evaluator.rb +1 -1
- data/lib/veritas/support/immutable.rb +22 -49
- data/lib/veritas/support/operation/binary.rb +3 -30
- data/lib/veritas/support/operation/unary.rb +3 -29
- data/lib/veritas/tuple.rb +19 -29
- data/lib/veritas/version.rb +1 -1
- data/lib/veritas.rb +1 -0
- data/spec/integration/veritas/relation/efficient_enumerable_spec.rb +3 -3
- data/spec/shared/hash_method_behavior.rb +7 -2
- data/spec/unit/date/pred_spec.rb +1 -1
- data/spec/unit/veritas/aggregate/equal_value_spec.rb +52 -0
- data/spec/unit/veritas/aggregate/hash_spec.rb +15 -0
- data/spec/unit/veritas/aliasable/inheritable_alias_spec.rb +1 -1
- data/spec/unit/veritas/comparator/compare_spec.rb +40 -0
- data/spec/unit/veritas/comparator/methods/eql_spec.rb +48 -0
- data/spec/unit/veritas/evaluator/context/respond_to_spec.rb +1 -1
- data/spec/unit/veritas/function/predicate/enumerable/call_spec.rb +36 -0
- data/spec/unit/veritas/function/unary/hash_spec.rb +18 -0
- data/spec/unit/veritas/immutable/freeze_spec.rb +2 -2
- data/spec/unit/veritas/immutable/memoize_spec.rb +13 -0
- data/spec/unit/veritas/immutable/module_methods/memoize_spec.rb +1 -1
- data/spec/unit/veritas/relation/empty/class_methods/new_spec.rb +30 -0
- data/spec/unit/veritas/relation/empty/each_spec.rb +20 -5
- data/spec/unit/veritas/relation/empty/size_spec.rb +11 -0
- data/spec/unit/veritas/relation/header/hash_spec.rb +1 -1
- data/spec/unit/veritas/relation/materialized/empty_spec.rb +0 -10
- data/spec/unit/veritas/relation/operation/order/direction_set/class_methods/coerce_spec.rb +12 -3
- data/tasks/metrics/heckle.rake +2 -3
- data/veritas.gemspec +21 -18
- metadata +36 -33
- data/README.rdoc +0 -143
- data/spec/unit/veritas/function/eql_spec.rb +0 -14
- data/spec/unit/veritas/function/equal_value_spec.rb +0 -14
- data/spec/unit/veritas/function/hash_spec.rb +0 -13
- data/spec/unit/veritas/immutable/memory/element_reference_spec.rb +0 -26
- data/spec/unit/veritas/immutable/memory/element_set_spec.rb +0 -19
- data/spec/unit/veritas/relation/operation/order/methods/order_spec.rb +0 -54
@@ -7,9 +7,11 @@ module Veritas
|
|
7
7
|
|
8
8
|
# A class that represents a tuple sort order for a set of attributes
|
9
9
|
class DirectionSet
|
10
|
-
extend Aliasable
|
10
|
+
extend Aliasable, Comparator
|
11
11
|
include Enumerable, Immutable
|
12
12
|
|
13
|
+
compare :to_ary
|
14
|
+
|
13
15
|
inheritable_alias(:| => :union)
|
14
16
|
|
15
17
|
# Instantiate a DirectionSet
|
@@ -24,7 +26,7 @@ module Veritas
|
|
24
26
|
#
|
25
27
|
# @api public
|
26
28
|
def self.new(directions)
|
27
|
-
directions = coerce_directions(directions
|
29
|
+
directions = coerce_directions(directions)
|
28
30
|
assert_unique_attributes(directions.map { |direction| direction.attribute })
|
29
31
|
super
|
30
32
|
end
|
@@ -37,7 +39,7 @@ module Veritas
|
|
37
39
|
#
|
38
40
|
# @api private
|
39
41
|
def self.coerce_directions(directions)
|
40
|
-
directions.map { |direction| Ascending.coerce(direction) }
|
42
|
+
Array(directions).map { |direction| Ascending.coerce(direction) }
|
41
43
|
end
|
42
44
|
|
43
45
|
# Assert the attributes are unique
|
@@ -212,36 +214,7 @@ module Veritas
|
|
212
214
|
#
|
213
215
|
# @api public
|
214
216
|
def ==(other)
|
215
|
-
|
216
|
-
to_ary == other.to_ary
|
217
|
-
end
|
218
|
-
|
219
|
-
# Compare the directions with other directions for equality
|
220
|
-
#
|
221
|
-
# @example
|
222
|
-
# directions.eql?(other) # => true or false
|
223
|
-
#
|
224
|
-
# @param [DirectionSet] other
|
225
|
-
# the other directions to compare with
|
226
|
-
#
|
227
|
-
# @return [Boolean]
|
228
|
-
#
|
229
|
-
# @api public
|
230
|
-
def eql?(other)
|
231
|
-
instance_of?(other.class) &&
|
232
|
-
to_ary.eql?(other.to_ary)
|
233
|
-
end
|
234
|
-
|
235
|
-
# Return the hash of the aliases
|
236
|
-
#
|
237
|
-
# @example
|
238
|
-
# hash = directions.hash
|
239
|
-
#
|
240
|
-
# @return [Fixnum]
|
241
|
-
#
|
242
|
-
# @api public
|
243
|
-
def hash
|
244
|
-
self.class.hash ^ to_ary.hash
|
217
|
+
cmp?(__method__, coerce(other))
|
245
218
|
end
|
246
219
|
|
247
220
|
# Test if there are no directions
|
@@ -291,6 +264,17 @@ module Veritas
|
|
291
264
|
end
|
292
265
|
end
|
293
266
|
|
267
|
+
# Coerce directions into a DirectionSet
|
268
|
+
#
|
269
|
+
# @param [DirectionSet, Array<Direction, Attribute>]
|
270
|
+
#
|
271
|
+
# @return [DirectionSet]
|
272
|
+
#
|
273
|
+
# @api private
|
274
|
+
def coerce(object)
|
275
|
+
self.class.coerce(object)
|
276
|
+
end
|
277
|
+
|
294
278
|
# Coerce directions into a DirectionSet
|
295
279
|
#
|
296
280
|
# @param [DirectionSet, Array<Direction, Attribute>]
|
@@ -302,7 +286,7 @@ module Veritas
|
|
302
286
|
object.kind_of?(DirectionSet) ? object : new(object)
|
303
287
|
end
|
304
288
|
|
305
|
-
memoize :
|
289
|
+
memoize :reverse
|
306
290
|
|
307
291
|
end # class DirectionSet
|
308
292
|
end # class Order
|
@@ -8,6 +8,8 @@ module Veritas
|
|
8
8
|
class Order < Relation
|
9
9
|
include Unary
|
10
10
|
|
11
|
+
compare :operand, :directions
|
12
|
+
|
11
13
|
# The relation sort order
|
12
14
|
#
|
13
15
|
# @return [Operation::Order::DirectionSet]
|
@@ -91,33 +93,6 @@ module Veritas
|
|
91
93
|
self
|
92
94
|
end
|
93
95
|
|
94
|
-
# Compare the Order with other relation for equality
|
95
|
-
#
|
96
|
-
# @example
|
97
|
-
# order.eql?(other) # => true or false
|
98
|
-
#
|
99
|
-
# @param [Relation] other
|
100
|
-
# the other relation to compare with
|
101
|
-
#
|
102
|
-
# @return [Boolean]
|
103
|
-
#
|
104
|
-
# @api public
|
105
|
-
def eql?(other)
|
106
|
-
super && directions.eql?(other.directions)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Return the hash of the order
|
110
|
-
#
|
111
|
-
# @example
|
112
|
-
# hash = order.hash
|
113
|
-
#
|
114
|
-
# @return [Fixnum]
|
115
|
-
#
|
116
|
-
# @api public
|
117
|
-
def hash
|
118
|
-
super ^ directions.hash
|
119
|
-
end
|
120
|
-
|
121
96
|
module Methods
|
122
97
|
|
123
98
|
# Return an ordered relation
|
@@ -130,47 +105,20 @@ module Veritas
|
|
130
105
|
#
|
131
106
|
# @yieldparam [Relation] relation
|
132
107
|
#
|
133
|
-
# @yieldreturn [Array<Direction>, Header]
|
108
|
+
# @yieldreturn [DirectionSet, Array<Direction>, Header]
|
134
109
|
#
|
135
110
|
# @return [Order]
|
136
111
|
#
|
137
112
|
# @api public
|
138
113
|
def sort_by
|
139
114
|
context = Evaluator::Context.new(header) { |context| yield context }
|
140
|
-
Order.new(self,
|
141
|
-
end
|
142
|
-
|
143
|
-
# Return an ordered relation (Deprecated)
|
144
|
-
#
|
145
|
-
# @deprecated Use #sort_by instead
|
146
|
-
#
|
147
|
-
# @example with no directions
|
148
|
-
# order = relation.order # sort by the header
|
149
|
-
#
|
150
|
-
# @example with a block
|
151
|
-
# order = relation.order { |r| [ r.a.desc, r.b ] }
|
152
|
-
#
|
153
|
-
# @yield [relation]
|
154
|
-
# optional block to evaluate for directions
|
155
|
-
#
|
156
|
-
# @yieldparam [Relation] relation
|
157
|
-
#
|
158
|
-
# @yieldreturn [Array<Direction>, Header]
|
159
|
-
#
|
160
|
-
# @return [Order]
|
161
|
-
#
|
162
|
-
# @api public
|
163
|
-
def order
|
164
|
-
warn "#{self.class}#order is deprecated and will be removed from Veritas 0.0.6"
|
165
|
-
sort_by { |context| block_given? ? yield(context) : header }
|
115
|
+
Order.new(self, context.yield)
|
166
116
|
end
|
167
117
|
|
168
118
|
end # module Methods
|
169
119
|
|
170
120
|
Relation.class_eval { include Methods }
|
171
121
|
|
172
|
-
memoize :hash
|
173
|
-
|
174
122
|
end # class Order
|
175
123
|
end # module Operation
|
176
124
|
end # class Relation
|
data/lib/veritas/relation.rb
CHANGED
@@ -4,8 +4,11 @@ module Veritas
|
|
4
4
|
|
5
5
|
# Abstract base class for Relation operations
|
6
6
|
class Relation
|
7
|
+
extend Comparator
|
7
8
|
include Immutable, Enumerable, Visitable
|
8
9
|
|
10
|
+
compare :header, :to_set
|
11
|
+
|
9
12
|
# The relation header
|
10
13
|
#
|
11
14
|
# @return [Header]
|
@@ -152,36 +155,7 @@ module Veritas
|
|
152
155
|
def ==(other)
|
153
156
|
other = coerce(other)
|
154
157
|
header == other.header &&
|
155
|
-
to_set ==
|
156
|
-
end
|
157
|
-
|
158
|
-
# Compare the relation with other relation for equality
|
159
|
-
#
|
160
|
-
# @example
|
161
|
-
# relation.eql?(other) # => true or false
|
162
|
-
#
|
163
|
-
# @param [Relation] other
|
164
|
-
# the other relation to compare with
|
165
|
-
#
|
166
|
-
# @return [Boolean]
|
167
|
-
#
|
168
|
-
# @api public
|
169
|
-
def eql?(other)
|
170
|
-
instance_of?(other.class) &&
|
171
|
-
header.eql?(other.header) &&
|
172
|
-
to_set.eql?(project_relation(other).to_set)
|
173
|
-
end
|
174
|
-
|
175
|
-
# Return the hash of the relation
|
176
|
-
#
|
177
|
-
# @example
|
178
|
-
# hash = relation.hash
|
179
|
-
#
|
180
|
-
# @return [Fixnum]
|
181
|
-
#
|
182
|
-
# @api public
|
183
|
-
def hash
|
184
|
-
self.class.hash ^ header.hash ^ to_set.hash
|
158
|
+
to_set == other.to_set
|
185
159
|
end
|
186
160
|
|
187
161
|
# Test if there are no tuples
|
@@ -200,17 +174,15 @@ module Veritas
|
|
200
174
|
|
201
175
|
# Coerce an Enumerable into a Relation
|
202
176
|
#
|
203
|
-
# @param [Enumerable]
|
204
|
-
# the
|
177
|
+
# @param [Enumerable] object
|
178
|
+
# the object to coerce
|
205
179
|
#
|
206
180
|
# @return [Relation]
|
207
181
|
#
|
208
182
|
# @api private
|
209
|
-
def coerce(
|
210
|
-
Relation.new(header,
|
183
|
+
def coerce(object)
|
184
|
+
project_relation(Relation.new(header, object))
|
211
185
|
end
|
212
186
|
|
213
|
-
memoize :hash
|
214
|
-
|
215
187
|
end # class Relation
|
216
188
|
end # module Veritas
|
@@ -17,15 +17,28 @@ module Veritas
|
|
17
17
|
#
|
18
18
|
# @api public
|
19
19
|
def inheritable_alias(aliases)
|
20
|
-
aliases.each
|
21
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
22
|
-
def #{new_method}(*args, &block) # def |(*args, &block)
|
23
|
-
self.#{original_method}(*args, &block) # self.union(*args, &block)
|
24
|
-
end # end
|
25
|
-
RUBY
|
26
|
-
end
|
20
|
+
aliases.each { |methods| define_inheritable_alias_method(*methods) }
|
27
21
|
self
|
28
22
|
end
|
29
23
|
|
24
|
+
private
|
25
|
+
|
26
|
+
# Create a new method alias for the original method
|
27
|
+
#
|
28
|
+
# @param [Symbol] new_method
|
29
|
+
#
|
30
|
+
# @param [Symbol] original_method
|
31
|
+
#
|
32
|
+
# @return [undefined]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
def define_inheritable_alias_method(new_method, original_method)
|
36
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
37
|
+
def #{new_method}(*args, &block) # def |(*args, &block)
|
38
|
+
self.#{original_method}(*args, &block) # self.union(*args, &block)
|
39
|
+
end # end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
|
30
43
|
end # module Aliasable
|
31
44
|
end # module Veritas
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Veritas
|
4
|
+
|
5
|
+
# Allows objects to be compared
|
6
|
+
module Comparator
|
7
|
+
|
8
|
+
# Setup default comparison methods for the object
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# compare :left, :right
|
12
|
+
#
|
13
|
+
# @param [Array<Symbol>] *methods
|
14
|
+
#
|
15
|
+
# @return [self]
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
def compare(*methods)
|
19
|
+
include Methods
|
20
|
+
define_hash_method(methods)
|
21
|
+
define_comparison_method(methods)
|
22
|
+
memoize :hash
|
23
|
+
private :cmp?
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Define a #hash method on the object
|
30
|
+
#
|
31
|
+
# The list of methods specify which methods' return values should be hashed
|
32
|
+
# and XOR'd together with the class's hash.
|
33
|
+
#
|
34
|
+
# @param [Array<#to_s>] methods
|
35
|
+
#
|
36
|
+
# @return [undefined]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
def define_hash_method(methods)
|
40
|
+
define_method(:hash) do
|
41
|
+
self.class.hash ^ methods.map { |method| send(method).hash }.inject(:^)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Define a private comparison method on the object
|
46
|
+
#
|
47
|
+
# The list of methods specify which methods' return values should be
|
48
|
+
# compared together using #== or #eql?
|
49
|
+
#
|
50
|
+
# @param [Array<#to_s>] methods
|
51
|
+
#
|
52
|
+
# @return [undefined]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
def define_comparison_method(methods)
|
56
|
+
define_method(:cmp?) do |comparator, other|
|
57
|
+
methods.all? { |method| send(method).send(comparator, other.send(method)) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# The comparison methods
|
62
|
+
module Methods
|
63
|
+
|
64
|
+
# Compare the object with other object for equality
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# object.eql?(other) # => true or false
|
68
|
+
#
|
69
|
+
# @param [Object] other
|
70
|
+
# the other object to compare with
|
71
|
+
#
|
72
|
+
# @return [Boolean]
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
def eql?(other)
|
76
|
+
instance_of?(other.class) && cmp?(__method__, other)
|
77
|
+
end
|
78
|
+
|
79
|
+
end # module Methods
|
80
|
+
end # module Comparator
|
81
|
+
end # module Veritas
|
@@ -29,7 +29,7 @@ module Veritas
|
|
29
29
|
#
|
30
30
|
# @api public
|
31
31
|
def freeze
|
32
|
-
@__memory =
|
32
|
+
@__memory = {} unless frozen?
|
33
33
|
super
|
34
34
|
end
|
35
35
|
|
@@ -38,14 +38,14 @@ module Veritas
|
|
38
38
|
# @example
|
39
39
|
# hash = object.memoized(:hash)
|
40
40
|
#
|
41
|
-
# @param [
|
41
|
+
# @param [Symbol] name
|
42
42
|
# the method name
|
43
43
|
#
|
44
44
|
# @return [Object]
|
45
45
|
#
|
46
46
|
# @api public
|
47
47
|
def memoized(name)
|
48
|
-
@__memory[
|
48
|
+
@__memory[name]
|
49
49
|
end
|
50
50
|
|
51
51
|
# Sets a memoized value for a method
|
@@ -53,7 +53,7 @@ module Veritas
|
|
53
53
|
# @example
|
54
54
|
# object.memoize(:hash, 12345)
|
55
55
|
#
|
56
|
-
# @param [
|
56
|
+
# @param [Symbol] name
|
57
57
|
# the method name
|
58
58
|
# @param [Object] value
|
59
59
|
# the value to memoize
|
@@ -62,7 +62,9 @@ module Veritas
|
|
62
62
|
#
|
63
63
|
# @api public
|
64
64
|
def memoize(name, value)
|
65
|
-
@__memory
|
65
|
+
unless @__memory.key?(name)
|
66
|
+
@__memory[name] = Immutable.freeze_object(value)
|
67
|
+
end
|
66
68
|
self
|
67
69
|
end
|
68
70
|
|
@@ -95,10 +97,10 @@ module Veritas
|
|
95
97
|
# @api public
|
96
98
|
def self.freeze_object(object)
|
97
99
|
case object
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
100
|
+
when Numeric, TrueClass, FalseClass, NilClass, Symbol
|
101
|
+
object
|
102
|
+
else
|
103
|
+
freeze_value(object)
|
102
104
|
end
|
103
105
|
end
|
104
106
|
|
@@ -161,23 +163,27 @@ module Veritas
|
|
161
163
|
# @api private
|
162
164
|
def memoize_method(method)
|
163
165
|
visibility = method_visibility(method)
|
164
|
-
|
166
|
+
define_memoize_method(method)
|
165
167
|
send(visibility, method)
|
166
168
|
end
|
167
169
|
|
168
|
-
#
|
170
|
+
# Define a memoized method that delegates to the original method
|
169
171
|
#
|
170
|
-
# @param [
|
172
|
+
# @param [Symbol] method
|
171
173
|
# the name of the method
|
172
174
|
#
|
173
175
|
# @return [undefined]
|
174
176
|
#
|
175
177
|
# @api private
|
176
|
-
def
|
178
|
+
def define_memoize_method(method)
|
177
179
|
original = instance_method(method)
|
178
|
-
|
179
|
-
|
180
|
-
@__memory
|
180
|
+
undef_method(method)
|
181
|
+
define_method(method) do |*args|
|
182
|
+
if @__memory.key?(method)
|
183
|
+
@__memory.fetch(method)
|
184
|
+
else
|
185
|
+
@__memory[method] = Immutable.freeze_object(original.bind(self).call(*args))
|
186
|
+
end
|
181
187
|
end
|
182
188
|
end
|
183
189
|
|
@@ -214,38 +220,5 @@ module Veritas
|
|
214
220
|
end
|
215
221
|
|
216
222
|
end # module ClassMethods
|
217
|
-
|
218
|
-
# Tracks the values for memoized methods
|
219
|
-
class Memory
|
220
|
-
|
221
|
-
# Get a frozen value from memory
|
222
|
-
#
|
223
|
-
# @example
|
224
|
-
# value = memory[ivar]
|
225
|
-
#
|
226
|
-
# @param [#to_s] ivar
|
227
|
-
# the name of the ivar to get the value for
|
228
|
-
#
|
229
|
-
# @return [Object]
|
230
|
-
#
|
231
|
-
# @api public
|
232
|
-
alias [] instance_variable_get
|
233
|
-
|
234
|
-
# Set a frozen value in memory
|
235
|
-
#
|
236
|
-
# @example
|
237
|
-
# memory[ivar] = value
|
238
|
-
#
|
239
|
-
# @param [#to_s] ivar
|
240
|
-
# the name of the ivar to set
|
241
|
-
# @param [Object] value
|
242
|
-
# the value to set
|
243
|
-
#
|
244
|
-
# @return [undefined]
|
245
|
-
#
|
246
|
-
# @api public
|
247
|
-
alias []= instance_variable_set
|
248
|
-
|
249
|
-
end # class Memory
|
250
223
|
end # module Immutable
|
251
224
|
end # module Veritas
|
@@ -3,8 +3,11 @@
|
|
3
3
|
module Veritas
|
4
4
|
module Operation
|
5
5
|
module Binary
|
6
|
+
extend Comparator
|
6
7
|
include Immutable
|
7
8
|
|
9
|
+
compare :left, :right
|
10
|
+
|
8
11
|
# The left operand for the operation
|
9
12
|
#
|
10
13
|
# @example
|
@@ -40,36 +43,6 @@ module Veritas
|
|
40
43
|
@right = Immutable.freeze_object(right)
|
41
44
|
end
|
42
45
|
|
43
|
-
# Compare the operation with the other operation for equality
|
44
|
-
#
|
45
|
-
# @example
|
46
|
-
# binary.eql?(other) # => true or false
|
47
|
-
#
|
48
|
-
# @param [Object] other
|
49
|
-
#
|
50
|
-
# @return [Boolean]
|
51
|
-
#
|
52
|
-
# @api public
|
53
|
-
def eql?(other)
|
54
|
-
instance_of?(other.class) &&
|
55
|
-
left.eql?(other.left) &&
|
56
|
-
right.eql?(other.right)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Return the hash of the left and right operands
|
60
|
-
#
|
61
|
-
# @example
|
62
|
-
# hash = binary.hash
|
63
|
-
#
|
64
|
-
# @return [Fixnum]
|
65
|
-
#
|
66
|
-
# @api public
|
67
|
-
def hash
|
68
|
-
self.class.hash ^ left.hash ^ right.hash
|
69
|
-
end
|
70
|
-
|
71
|
-
memoize :hash
|
72
|
-
|
73
46
|
end # module Binary
|
74
47
|
end # module Operation
|
75
48
|
end # module Veritas
|
@@ -3,8 +3,11 @@
|
|
3
3
|
module Veritas
|
4
4
|
module Operation
|
5
5
|
module Unary
|
6
|
+
extend Comparator
|
6
7
|
include Immutable
|
7
8
|
|
9
|
+
compare :operand
|
10
|
+
|
8
11
|
# The operand to the operation
|
9
12
|
#
|
10
13
|
# @example
|
@@ -27,35 +30,6 @@ module Veritas
|
|
27
30
|
@operand = Immutable.freeze_object(operand)
|
28
31
|
end
|
29
32
|
|
30
|
-
# Compare the operation with the other operation for equality
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# unary.eql?(other) # => true or false
|
34
|
-
#
|
35
|
-
# @param [Object] other
|
36
|
-
#
|
37
|
-
# @return [Boolean]
|
38
|
-
#
|
39
|
-
# @api public
|
40
|
-
def eql?(other)
|
41
|
-
instance_of?(other.class) &&
|
42
|
-
operand.eql?(other.operand)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Return the hash of the operand
|
46
|
-
#
|
47
|
-
# @example
|
48
|
-
# hash = unary.hash
|
49
|
-
#
|
50
|
-
# @return [Fixnum]
|
51
|
-
#
|
52
|
-
# @api public
|
53
|
-
def hash
|
54
|
-
self.class.hash ^ operand.hash
|
55
|
-
end
|
56
|
-
|
57
|
-
memoize :hash
|
58
|
-
|
59
33
|
end # module Unary
|
60
34
|
end # module Operation
|
61
35
|
end # module Veritas
|
data/lib/veritas/tuple.rb
CHANGED
@@ -4,8 +4,11 @@ module Veritas
|
|
4
4
|
|
5
5
|
# A set of objects representing a unique fact in a relation
|
6
6
|
class Tuple
|
7
|
+
extend Comparator
|
7
8
|
include Immutable
|
8
9
|
|
10
|
+
compare :data
|
11
|
+
|
9
12
|
# The tuple header
|
10
13
|
#
|
11
14
|
# @return [Header]
|
@@ -136,48 +139,35 @@ module Veritas
|
|
136
139
|
#
|
137
140
|
# @api public
|
138
141
|
def ==(other)
|
139
|
-
|
140
|
-
data == other.data
|
142
|
+
cmp?(__method__, coerce(other))
|
141
143
|
end
|
142
144
|
|
143
|
-
#
|
145
|
+
# Return a string representing the tuple data
|
144
146
|
#
|
145
147
|
# @example
|
146
|
-
# tuple
|
147
|
-
#
|
148
|
-
# @param [Tuple] other
|
149
|
-
# the other tuple to compare with
|
148
|
+
# tuple.inspect # => "{<Attribute::Integer name: id>=>1}"
|
150
149
|
#
|
151
|
-
# @return [
|
150
|
+
# @return [String]
|
152
151
|
#
|
153
152
|
# @api public
|
154
|
-
def
|
155
|
-
|
156
|
-
data.eql?(other.data)
|
153
|
+
def inspect
|
154
|
+
data.inspect
|
157
155
|
end
|
158
156
|
|
159
|
-
|
160
|
-
#
|
161
|
-
# @example
|
162
|
-
# hash = tuple.hash
|
163
|
-
#
|
164
|
-
# @return [Fixnum]
|
165
|
-
#
|
166
|
-
# @api public
|
167
|
-
def hash
|
168
|
-
self.class.hash ^ data.hash
|
169
|
-
end
|
157
|
+
private
|
170
158
|
|
171
|
-
#
|
159
|
+
# Coerce an Array-like object into a Tuple
|
172
160
|
#
|
173
|
-
# @
|
174
|
-
# tuple
|
161
|
+
# @param [Header] header
|
162
|
+
# the tuple header
|
163
|
+
# @param [Tuple, #to_ary]
|
164
|
+
# the tuple or tuple data
|
175
165
|
#
|
176
|
-
# @return [
|
166
|
+
# @return [Tuple]
|
177
167
|
#
|
178
|
-
# @api
|
179
|
-
def
|
180
|
-
|
168
|
+
# @api private
|
169
|
+
def coerce(object)
|
170
|
+
self.class.coerce(header, object)
|
181
171
|
end
|
182
172
|
|
183
173
|
# Coerce an Array-like object into a Tuple
|
data/lib/veritas/version.rb
CHANGED