Class: Alf::Aggregator
- Inherits:
-
Object
- Object
- Alf::Aggregator
- Extended by:
- Support::Registry
- Defined in:
- lib/alf/aggregator.rb,
lib/alf/aggregator/avg.rb,
lib/alf/aggregator/max.rb,
lib/alf/aggregator/min.rb,
lib/alf/aggregator/sum.rb,
lib/alf/aggregator/count.rb,
lib/alf/aggregator/concat.rb,
lib/alf/aggregator/stddev.rb,
lib/alf/aggregator/collect.rb,
lib/alf/aggregator/variance.rb
Overview
Aggregation operator.
This class provides a basis for implementing aggregation operators. It should always be used as a superclass for such implementations.
Aggregation operators are made available through factory methods on the Aggregator class itself:
Aggregator.count
Aggregator.sum{ qty }
The coercion method should always be used for building aggregators from lispy source code:
Aggregator.coerce("count")
Aggregator.coerce("sum{ qty }")
Once built, aggregators can be used either in black-box or white-box modes.
relation = ...
agg = Aggregator.sum{ qty }
# Black box mode:
result = agg.aggregate(relation)
# White box mode:
memo = agg.least
relation.each do |tuple|
memo = agg.happens(memo, tuple)
end
result = agg.finalize(memo)
Defined Under Namespace
Classes: Avg, Collect, Concat, Count, Max, Min, Stddev, Sum, Variance
Instance Attribute Summary collapse
-
#functor ⇒ TupleExpression
readonly
The underlying functor.
-
#options ⇒ Hash
readonly
Aggregation options.
-
#source ⇒ String
Source code of the aggregator, if any.
Class Method Summary collapse
-
.coerce(arg) ⇒ Aggregator
Coerces ‘arg` to an Aggregator.
-
.inherited(clazz) ⇒ Object
Automatically installs factory methods for inherited classes.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Checks equality with another aggregator.
-
#aggregate(enum) ⇒ Object
Aggregates over an enumeration of tuples.
-
#default_options ⇒ Hash
Returns the default options to use.
-
#finalize(memo) ⇒ Object
This method finalizes an aggregation.
-
#happens(memo, scope) ⇒ Object
This method is called on each aggregated tuple and must return an updated memo value.
-
#has_source_code! ⇒ String
Asserts that this aggregator knows its source code or raises a NotImplementedError.
-
#infer_type ⇒ Object
Infers the resulting type from expression source code.
-
#initialize(*args, &block) ⇒ Aggregator
constructor
Creates an Aggregator instance.
-
#least ⇒ Object
Returns the least value, which is the one to use on an empty set.
-
#to_lispy ⇒ String
Returns a lispy expression.
Methods included from Support::Registry
each, listen, listeners, register, registered
Constructor Details
#initialize(*args, &block) ⇒ Aggregator
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/alf/aggregator.rb', line 101 def initialize(*args, &block) @options = args.push(block) if block args.each do |arg| case arg when Symbol, Proc then @functor = Support.coerce(arg, TupleExpression) when Hash then @options = @options.merge(arg) else raise ArgumentError, "Unexpected `#{arg}`" end end end |
Instance Attribute Details
#functor ⇒ TupleExpression (readonly)
Returns the underlying functor.
90 91 92 |
# File 'lib/alf/aggregator.rb', line 90 def functor @functor end |
#options ⇒ Hash (readonly)
Returns Aggregation options.
87 88 89 |
# File 'lib/alf/aggregator.rb', line 87 def @options end |
#source ⇒ String
Returns source code of the aggregator, if any.
93 94 95 |
# File 'lib/alf/aggregator.rb', line 93 def source @source end |
Class Method Details
.coerce(arg) ⇒ Aggregator
Coerces ‘arg` to an Aggregator
Implemented coercions are:
-
Aggregator -> self
-
String -> through factory methods on self
76 77 78 79 80 81 82 83 |
# File 'lib/alf/aggregator.rb', line 76 def coerce(arg) case arg when Aggregator arg else raise ArgumentError, "Invalid arg `arg` for Aggregator()" end end |
.inherited(clazz) ⇒ Object
Automatically installs factory methods for inherited classes.
63 64 65 |
# File 'lib/alf/aggregator.rb', line 63 def inherited(clazz) register(clazz, Aggregator) end |
Instance Method Details
#==(other) ⇒ Boolean
Checks equality with another aggregator
199 200 201 202 203 204 |
# File 'lib/alf/aggregator.rb', line 199 def ==(other) return false unless other.is_a?(Aggregator) has_source_code! == other.has_source_code! rescue NotImplementedError super end |
#aggregate(enum) ⇒ Object
Aggregates over an enumeration of tuples.
164 165 166 167 |
# File 'lib/alf/aggregator.rb', line 164 def aggregate(enum) scope = Support::TupleScope.new finalize(enum.inject(least){|m,t| happens(m, scope.__set_tuple(t))}) end |
#default_options ⇒ Hash
Returns the default options to use
117 118 119 |
# File 'lib/alf/aggregator.rb', line 117 def {} end |
#finalize(memo) ⇒ Object
This method finalizes an aggregation.
Argument memo is either least or the result of aggregating through happens. The default implementation simply returns memo. The method is intended to be overriden for complex aggregations that need statefull information such as ‘avg`.
156 157 158 |
# File 'lib/alf/aggregator.rb', line 156 def finalize(memo) memo end |
#happens(memo, scope) ⇒ Object
This method is called on each aggregated tuple and must return an updated memo value. It can be seen as the block typically given to Enumerable.inject.
The default implementation collects the pre-value on the tuple and delegates to _happens.
142 143 144 145 |
# File 'lib/alf/aggregator.rb', line 142 def happens(memo, scope) raise unless Support::TupleScope===scope _happens(memo, @functor.evaluate(scope)) end |
#has_source_code! ⇒ String
Asserts that this aggregator knows its source code or raises a NotImplementedError.
178 179 180 181 182 183 184 |
# File 'lib/alf/aggregator.rb', line 178 def has_source_code! if source.nil? raise NotImplementedError, "No known source code for this aggregator" else source end end |
#infer_type ⇒ Object
Infers the resulting type from expression source code
170 171 172 |
# File 'lib/alf/aggregator.rb', line 170 def infer_type Object end |
#least ⇒ Object
Returns the least value, which is the one to use on an empty set.
This method is intended to be overriden by subclasses; default implementation returns nil.
128 129 130 |
# File 'lib/alf/aggregator.rb', line 128 def least nil end |
#to_lispy ⇒ String
Returns a lispy expression
189 190 191 192 193 |
# File 'lib/alf/aggregator.rb', line 189 def to_lispy has_source_code! rescue NotImplementedError "#{Support.rubycase_name(self.class)}{|t| [code unavailable] }" end |