veritas 0.0.6 → 0.0.7

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.
Files changed (77) hide show
  1. data/.travis.yml +10 -4
  2. data/Gemfile +1 -1
  3. data/TODO +10 -0
  4. data/config/flay.yml +1 -1
  5. data/config/flog.yml +1 -1
  6. data/config/roodi.yml +2 -2
  7. data/config/site.reek +2 -1
  8. data/lib/veritas.rb +2 -2
  9. data/lib/veritas/algebra/join.rb +13 -91
  10. data/lib/veritas/algebra/product.rb +4 -1
  11. data/lib/veritas/attribute.rb +1 -1
  12. data/lib/veritas/function/connective/negation.rb +13 -1
  13. data/lib/veritas/function/numeric/absolute.rb +5 -19
  14. data/lib/veritas/function/numeric/unary.rb +3 -0
  15. data/lib/veritas/function/numeric/unary_minus.rb +5 -19
  16. data/lib/veritas/function/numeric/unary_plus.rb +5 -21
  17. data/lib/veritas/function/proposition.rb +3 -28
  18. data/lib/veritas/function/string/length.rb +0 -1
  19. data/lib/veritas/function/unary.rb +47 -0
  20. data/lib/veritas/relation.rb +16 -2
  21. data/lib/veritas/relation/header.rb +48 -41
  22. data/lib/veritas/relation/operation/order/direction.rb +13 -1
  23. data/lib/veritas/relation/operation/order/direction_set.rb +9 -198
  24. data/lib/veritas/relation/operation/reverse.rb +0 -2
  25. data/lib/veritas/support/comparator.rb +1 -1
  26. data/lib/veritas/support/evaluator.rb +3 -0
  27. data/lib/veritas/support/immutable.rb +33 -8
  28. data/lib/veritas/tuple.rb +8 -6
  29. data/lib/veritas/version.rb +1 -1
  30. data/spec/integration/veritas/algebra/projection_spec.rb +1 -1
  31. data/spec/integration/veritas/relation/efficient_enumerable_spec.rb +40 -15
  32. data/spec/rcov.opts +1 -0
  33. data/spec/shared/hash_method_behavior.rb +10 -5
  34. data/spec/spec_helper.rb +1 -1
  35. data/spec/unit/veritas/algebra/extension/class_methods/new_spec.rb +1 -1
  36. data/spec/unit/veritas/algebra/join/class_methods/new_spec.rb +1 -1
  37. data/spec/unit/veritas/algebra/join/each_spec.rb +36 -9
  38. data/spec/unit/veritas/aliasable/inheritable_alias_spec.rb +1 -1
  39. data/spec/unit/veritas/comparator/compare_spec.rb +4 -1
  40. data/spec/unit/veritas/evaluator/context/method_missing_spec.rb +7 -1
  41. data/spec/unit/veritas/function/connective/negation/class_methods/operation_spec.rb +11 -0
  42. data/spec/unit/veritas/function/numeric/absolute/class_methods/operation_spec.rb +11 -0
  43. data/spec/unit/veritas/function/numeric/unary_minus/class_methods/operation_spec.rb +11 -0
  44. data/spec/unit/veritas/function/numeric/unary_plus/class_methods/operation_spec.rb +11 -0
  45. data/spec/unit/veritas/function/unary/callable/call_spec.rb +23 -0
  46. data/spec/unit/veritas/function/unary/callable/included_spec.rb +23 -0
  47. data/spec/unit/veritas/function/unary/inspect_spec.rb +34 -0
  48. data/spec/unit/veritas/immutable/fixtures/classes.rb +3 -3
  49. data/spec/unit/veritas/immutable/module_methods/memoize_spec.rb +20 -10
  50. data/spec/unit/veritas/relation/class_methods/coerce_spec.rb +23 -0
  51. data/spec/unit/veritas/relation/each_spec.rb +1 -1
  52. data/spec/unit/veritas/relation/equal_value_spec.rb +12 -0
  53. data/spec/unit/veritas/relation/header/call_spec.rb +23 -0
  54. data/spec/unit/veritas/relation/header/class_methods/coerce_spec.rb +1 -1
  55. data/spec/unit/veritas/relation/header/class_methods/new_spec.rb +2 -2
  56. data/spec/unit/veritas/relation/header/each_spec.rb +1 -1
  57. data/spec/unit/veritas/relation/header/empty_spec.rb +5 -4
  58. data/spec/unit/veritas/relation/header/intersect_spec.rb +18 -4
  59. data/spec/unit/veritas/relation/operation/binary/class_methods/new_spec.rb +25 -25
  60. data/spec/unit/veritas/relation/operation/order/direction/name_spec.rb +13 -0
  61. data/spec/unit/veritas/relation/operation/order/direction_set/class_methods/new_spec.rb +1 -1
  62. data/spec/unit/veritas/relation/operation/order/direction_set/equal_value_spec.rb +13 -0
  63. data/spec/unit/veritas/tuple/call_spec.rb +25 -0
  64. data/spec/unit/veritas/tuple/class_methods/coerce_spec.rb +1 -1
  65. data/tasks/metrics/ci.rake +2 -2
  66. data/tasks/metrics/flay.rake +1 -1
  67. data/tasks/metrics/flog.rake +5 -3
  68. data/tasks/metrics/heckle.rake +18 -11
  69. data/tasks/metrics/reek.rake +1 -1
  70. data/tasks/spec.rake +23 -14
  71. data/veritas.gemspec +14 -8
  72. metadata +31 -25
  73. data/spec/unit/veritas/relation/header/element_reference_spec.rb +0 -21
  74. data/spec/unit/veritas/relation/operation/order/direction_set/each_spec.rb +0 -32
  75. data/spec/unit/veritas/relation/operation/order/direction_set/empty_spec.rb +0 -21
  76. data/spec/unit/veritas/relation/operation/order/direction_set/union_spec.rb +0 -18
  77. data/spec/unit/veritas/tuple/element_reference_spec.rb +0 -22
data/.travis.yml CHANGED
@@ -1,11 +1,17 @@
1
+ language: ruby
1
2
  bundler_args: --without guard metrics
2
3
  script: "bundle exec rake spec"
3
4
  rvm:
4
5
  - 1.8.7
5
6
  - 1.9.2
6
7
  - 1.9.3
7
- - ruby-head
8
+ - jruby-18mode
9
+ - jruby-19mode
10
+ - rbx-18mode
11
+ - rbx-19mode
8
12
  - ree
9
- - jruby
10
- - rbx
11
- - rbx-2.0
13
+ - ruby-head
14
+ - jruby-head
15
+ notifications:
16
+ email:
17
+ - dan.kubb@gmail.com
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- source :rubygems
3
+ source 'https://rubygems.org'
4
4
 
5
5
  group :development do
6
6
  gem 'backports', '~> 2.3.0'
data/TODO CHANGED
@@ -1,3 +1,13 @@
1
+ * Convert Tuple to a Struct
2
+ * Make Header a "Struct Class", and copy all the Header instance methods to
3
+ the class level. Move all the Tuple instance methods into the Header
4
+ instance.
5
+ * Rename Header as Tuple
6
+ * Make sure the Tuple has a class level method called #header that returns
7
+ the set of attributes.
8
+ * Use a class variable to store each "Tuple class" so that anything with a
9
+ similar header will be reused.
10
+
1
11
  * Remove Order, Reverse, Limit and Offset from the Relation inheritance chain
2
12
  * Instead make it so they are proxy classes that wrap Relations, but
3
13
  proxy method calls to the Relation methods, and then wrap the return
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 68
3
- total_score: 682
3
+ total_score: 708
data/config/flog.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 23.3
2
+ threshold: 21.9
data/config/roodi.yml CHANGED
@@ -2,7 +2,7 @@
2
2
  AbcMetricMethodCheck: { score: 10.3 }
3
3
  AssignmentInConditionalCheck: { }
4
4
  CaseMissingElseCheck: { }
5
- ClassLineCountCheck: { line_count: 289 }
5
+ ClassLineCountCheck: { line_count: 292 }
6
6
  ClassNameCheck: { pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ }
7
7
  ClassVariableCheck: { }
8
8
  CyclomaticComplexityBlockCheck: { complexity: 2 }
@@ -12,7 +12,7 @@ ForLoopCheck: { }
12
12
  # TODO: decrease line_count to 5 to 10
13
13
  MethodLineCountCheck: { line_count: 14 }
14
14
  MethodNameCheck: { pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|[+*&|-])\z/ }
15
- ModuleLineCountCheck: { line_count: 291 }
15
+ ModuleLineCountCheck: { line_count: 294 }
16
16
  ModuleNameCheck: { pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ }
17
17
  # TODO: decrease parameter_count to 2 or less
18
18
  ParameterNumberCheck: { parameter_count: 3 }
data/config/site.reek CHANGED
@@ -86,7 +86,8 @@ DataClump:
86
86
  # all of these classes have utility class methods that are
87
87
  # incorrectly identified as instance methods
88
88
  Veritas::Relation::Operation::Binary::ClassMethods,
89
- Veritas::Relation::Operation::Set::ClassMethods
89
+ Veritas::Relation::Operation::Set::ClassMethods,
90
+ Veritas::Immutable
90
91
  ]
91
92
  enabled: true
92
93
  max_copies: 1
data/lib/veritas.rb CHANGED
@@ -147,8 +147,8 @@ module Veritas
147
147
  # Raised when a binary operation mixes ordered and unordered relations
148
148
  class RelationMismatchError < StandardError; end
149
149
 
150
- # Raised when an attribute is a duplicate of another in the header
151
- class DuplicateAttributeError < StandardError; end
150
+ # Raised when a name is a duplicate of another name in a set
151
+ class DuplicateNameError < StandardError; end
152
152
 
153
153
  # Represent an undefined argument
154
154
  Undefined = Object.new.freeze
@@ -14,41 +14,6 @@ module Veritas
14
14
  # @api private
15
15
  attr_reader :join_header
16
16
 
17
- # Instantiate a new Join
18
- #
19
- # @example
20
- # join = Join.new(left, right)
21
- #
22
- # @param [Relation] left
23
- # @param [Relation] right
24
- #
25
- # @return [Join]
26
- #
27
- # @api public
28
- def self.new(left, right)
29
- assert_joinable_headers(left, right)
30
- super
31
- end
32
-
33
- # Assert the headers have common attributes
34
- #
35
- # @param [Relation] left
36
- # @param [Relation] right
37
- #
38
- # @return [undefined]
39
- #
40
- # @raise [InvalidHeaderError]
41
- # raised if there are no common attributes between the headers
42
- #
43
- # @api private
44
- def self.assert_joinable_headers(left, right)
45
- if (left.header & right.header).empty?
46
- raise InvalidHeaderError, 'the headers must have common attributes'
47
- end
48
- end
49
-
50
- private_class_method :assert_joinable_headers
51
-
52
17
  # Initialize a Join
53
18
  #
54
19
  # @param [Relation] left
@@ -59,9 +24,9 @@ module Veritas
59
24
  # @api private
60
25
  def initialize(left, right)
61
26
  super
62
- right_header = right.header
63
- @join_header = left.header & right_header
64
- @remainder_header = right_header - join_header
27
+ right_header = right.header
28
+ @join_header = left.header & right_header
29
+ @disjoint_header = right_header - join_header
65
30
  end
66
31
 
67
32
  # Iterate over each tuple in the set
@@ -85,9 +50,7 @@ module Veritas
85
50
 
86
51
  left.each do |left_tuple|
87
52
  right_tuples = index[join_tuple(left_tuple)]
88
- if right_tuples
89
- util.combine_tuples(header, left_tuple, right_tuples, &block)
90
- end
53
+ util.combine_tuples(header, left_tuple, right_tuples, &block)
91
54
  end
92
55
 
93
56
  self
@@ -101,16 +64,12 @@ module Veritas
101
64
  #
102
65
  # @api private
103
66
  def build_index
104
- index = {}
105
-
106
- right.each do |tuple|
107
- (index[join_tuple(tuple)] ||= Set.new) << remainder_tuple(tuple)
108
- end
109
-
67
+ index = Hash.new { |hash, tuple| hash[tuple] = Set.new }
68
+ right.each { |tuple| index[join_tuple(tuple)] << disjoint_tuple(tuple) }
110
69
  index
111
70
  end
112
71
 
113
- # Generate a tuple with only the common attributes used for the join
72
+ # Generate a tuple with the join attributes between relations
114
73
  #
115
74
  # @return [Tuple]
116
75
  #
@@ -119,13 +78,13 @@ module Veritas
119
78
  tuple.project(join_header)
120
79
  end
121
80
 
122
- # Generate a tuple with the disjoint attributes to use in the join
81
+ # Generate a tuple with the disjoint attributes between relations
123
82
  #
124
83
  # @return [Tuple]
125
84
  #
126
85
  # @api private
127
- def remainder_tuple(tuple)
128
- tuple.project(@remainder_header)
86
+ def disjoint_tuple(tuple)
87
+ tuple.project(@disjoint_header)
129
88
  end
130
89
 
131
90
  module Methods
@@ -157,46 +116,9 @@ module Veritas
157
116
  #
158
117
  # @api public
159
118
  def join(other)
160
- if block_given?
161
- theta_join(other) { |relation| yield relation }
162
- else
163
- natural_join(other)
164
- end
165
- end
166
-
167
- private
168
-
169
- # Return a relation that is the natural join
170
- #
171
- # @param [Relation] other
172
- # the other relation to join
173
- #
174
- # @return [Join]
175
- #
176
- # @api private
177
- def natural_join(other)
178
- Join.new(self, other)
179
- end
180
-
181
- # Return a relation that is a restricted cartesian product
182
- #
183
- # @param [Relation] other
184
- # the other relation to join
185
- #
186
- # @yield [relation]
187
- # optional block to restrict the tuples with
188
- #
189
- # @yieldparam [Relation] relation
190
- # the context to evaluate the restriction with
191
- #
192
- # @yieldreturn [Function, #call]
193
- # predicate to restrict the tuples with
194
- #
195
- # @return [Restriction]
196
- #
197
- # @api private
198
- def theta_join(other)
199
- product(other).restrict { |relation| yield relation }
119
+ relation = Join.new(self, other)
120
+ relation = relation.restrict { |context| yield context } if block_given?
121
+ relation
200
122
  end
201
123
 
202
124
  end # module Methods
@@ -58,10 +58,13 @@ module Veritas
58
58
  # @api public
59
59
  def each(&block)
60
60
  return to_enum unless block_given?
61
+ util = Relation::Operation::Combination
61
62
  right_tuples = right.to_a
63
+
62
64
  left.each do |left_tuple|
63
- Relation::Operation::Combination.combine_tuples(header, left_tuple, right_tuples, &block)
65
+ util.combine_tuples(header, left_tuple, right_tuples, &block)
64
66
  end
67
+
65
68
  self
66
69
  end
67
70
 
@@ -131,7 +131,7 @@ module Veritas
131
131
  #
132
132
  # @api public
133
133
  def call(tuple)
134
- tuple[self]
134
+ tuple.call(self)
135
135
  end
136
136
 
137
137
  # Rename an attribute
@@ -8,6 +8,18 @@ module Veritas
8
8
  class Negation < Connective
9
9
  include Unary, Unary::Invertible
10
10
 
11
+ # Return the negation operation
12
+ #
13
+ # @example
14
+ # Negation.operation # => :!
15
+ #
16
+ # @return [Symbol]
17
+ #
18
+ # @api public
19
+ def self.operation
20
+ :'!'
21
+ end
22
+
11
23
  # Evaluate the operands using a logical NOT
12
24
  #
13
25
  # @example with true operand
@@ -23,7 +35,7 @@ module Veritas
23
35
  # @api public
24
36
  def self.call(operand)
25
37
  ! operand
26
- end
38
+ end unless Object.method_defined?('!')
27
39
 
28
40
  # Return the operand
29
41
  #
@@ -8,30 +8,16 @@ module Veritas
8
8
  class Absolute < Numeric
9
9
  include Unary
10
10
 
11
- # Return the absolute value
11
+ # Return the absolute operation
12
12
  #
13
13
  # @example
14
- # absolute_value = Absolute.call(value)
14
+ # Absolute.operation # => :abs
15
15
  #
16
- # @param [Numeric] value
17
- #
18
- # @return [Numeric]
19
- #
20
- # @api public
21
- def self.call(value)
22
- value.abs
23
- end
24
-
25
- # Return a string representing the absolute function
26
- #
27
- # @example
28
- # absolute.inspect # => "ABS(-1)"
29
- #
30
- # @return [String]
16
+ # @return [Symbol]
31
17
  #
32
18
  # @api public
33
- def inspect
34
- "ABS(#{operand.inspect})"
19
+ def self.operation
20
+ :abs
35
21
  end
36
22
 
37
23
  module Methods
@@ -10,6 +10,9 @@ module Veritas
10
10
 
11
11
  # Return the type returned from #call
12
12
  #
13
+ # @example
14
+ # unary.type # => Attribute::Numeric
15
+ #
13
16
  # @return [Class<Attribute::Numeric>]
14
17
  #
15
18
  # @api public
@@ -8,18 +8,16 @@ module Veritas
8
8
  class UnaryMinus < Numeric
9
9
  include Unary
10
10
 
11
- # Return the value subtracted from 0
11
+ # Return the unary minus operation
12
12
  #
13
13
  # @example
14
- # negated_value = UnaryMinus.call(value)
14
+ # UnaryMinus.operation # => :-@
15
15
  #
16
- # @param [Numeric] value
17
- #
18
- # @return [Numeric]
16
+ # @return [Symbol]
19
17
  #
20
18
  # @api public
21
- def self.call(value)
22
- -value
19
+ def self.operation
20
+ :-@
23
21
  end
24
22
 
25
23
  # Return the inverse function class
@@ -34,18 +32,6 @@ module Veritas
34
32
  UnaryPlus
35
33
  end
36
34
 
37
- # Return a string representing the unary minus function
38
- #
39
- # @example
40
- # unary_minus.inspect # => "-1"
41
- #
42
- # @return [String]
43
- #
44
- # @api public
45
- def inspect
46
- "-(#{operand.inspect})"
47
- end
48
-
49
35
  module Methods
50
36
  extend Aliasable
51
37
 
@@ -8,20 +8,16 @@ module Veritas
8
8
  class UnaryPlus < Numeric
9
9
  include Unary
10
10
 
11
- # Return the value added to 0
12
- #
13
- # This is a noop.
11
+ # Return the unary plus operation
14
12
  #
15
13
  # @example
16
- # new_value = UnaryPlus.call(value)
17
- #
18
- # @param [Numeric] value
14
+ # UnaryPlus.operation # => :+@
19
15
  #
20
- # @return [Numeric]
16
+ # @return [Symbol]
21
17
  #
22
18
  # @api public
23
- def self.call(value)
24
- +value
19
+ def self.operation
20
+ :+@
25
21
  end
26
22
 
27
23
  # Return the inverse function class
@@ -36,18 +32,6 @@ module Veritas
36
32
  UnaryMinus
37
33
  end
38
34
 
39
- # Return a string representing the unary plus function
40
- #
41
- # @example
42
- # unary_plus.inspect # => "+1"
43
- #
44
- # @return [String]
45
- #
46
- # @api public
47
- def inspect
48
- "+(#{operand.inspect})"
49
- end
50
-
51
35
  module Methods
52
36
  extend Aliasable
53
37
 
@@ -5,12 +5,15 @@ module Veritas
5
5
 
6
6
  # Abstract base class for logical propositions
7
7
  class Proposition < Function
8
+ extend Comparator
8
9
  include AbstractClass,
9
10
  Singleton,
10
11
  Function::Connective::Conjunction::Methods,
11
12
  Function::Connective::Disjunction::Methods,
12
13
  Function::Connective::Negation::Methods
13
14
 
15
+ compare # only compare instances with the same superclass
16
+
14
17
  # Instantiate a new Proposition
15
18
  #
16
19
  # @example using a true value
@@ -105,32 +108,6 @@ module Veritas
105
108
  kind_of?(other.class) || other.kind_of?(self.class)
106
109
  end
107
110
 
108
- # Compare the proposition with other proposition for equality
109
- #
110
- # @example
111
- # proposition.eql?(other) # => true or false
112
- #
113
- # @param [Proposition] other
114
- #
115
- # @return [Boolean]
116
- #
117
- # @api public
118
- def eql?(other)
119
- instance_of?(other.class)
120
- end
121
-
122
- # Return the hash of the proposition
123
- #
124
- # @example
125
- # hash = proposition.hash
126
- #
127
- # @return [Fixnum]
128
- #
129
- # @api public
130
- def hash
131
- self.class.hash
132
- end
133
-
134
111
  # Return a string representing the proposition
135
112
  #
136
113
  # @example
@@ -143,8 +120,6 @@ module Veritas
143
120
  call.inspect
144
121
  end
145
122
 
146
- memoize :hash
147
-
148
123
  end # class Proposition
149
124
  end # module Algebra
150
125
  end # module Veritas