veritas 0.0.6 → 0.0.7

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