lib/axiom/relation/operation/offset.rb
# encoding: utf-8
module Axiom
class Relation
module Operation
# A class representing an offset relation
class Offset < Relation
include Unary
include Equalizer.new(:operand, :offset)
# Return the offset
#
# @example
# offset = offset_relation.offset
#
# @return [Integer]
#
# @api public
attr_reader :offset
# The relation sort order
#
# @return [Operation::Sorted::DirectionSet]
#
# @api private
attr_reader :directions
# Instantiate a new Offset
#
# @example
# offset_relation = Offset.new(operand, offset)
#
# @param [Relation] operand
# the relation to offset
# @param [Integer] offset
# the offset of the operand to drop
#
# @return [Offset]
#
# @api public
def self.new(operand, offset)
assert_sorted_operand(operand)
assert_valid_offset(offset)
super
end
# Assert the operand is sorted
#
# @param [Relation] operand
#
# @return [undefined]
#
# @raise [SortededRelationRequiredError]
# raised if the operand is unsorted
#
# @api private
def self.assert_sorted_operand(operand)
if operand.header.size != operand.directions.size
fail SortededRelationRequiredError, 'can only offset a sorted operand'
end
end
# Assert the offset is valid
#
# @param [Integer] offset
#
# @return [undefined]
#
# @raise [InvalidOffsetError]
# raised if the offset is less than 0
#
# @api private
def self.assert_valid_offset(offset)
if offset.nil? || offset < 0
fail InvalidOffsetError, "offset must be greater than or equal to 0, but was #{offset.inspect}"
end
end
private_class_method :assert_sorted_operand, :assert_valid_offset
# Initialize an Offset
#
# @param [Relation] operand
# the relation to offset
# @param [Integer] offset
# the offset of the operand to drop
#
# @return [undefined]
#
# @api private
def initialize(operand, offset)
super(operand)
@offset = offset
@directions = operand.directions
end
# Iterate over each tuple in the set
#
# @example
# offset_relation = Offset.new(operand, offset)
# offset_relation.each { |tuple| ... }
#
# @yield [tuple]
#
# @yieldparam [Tuple] tuple
# each tuple in the set
#
# @return [self]
#
# @api public
def each
return to_enum unless block_given?
operand.each_with_index do |tuple, index|
yield tuple if index >= @offset
end
self
end
# Raise an exception when inserting into the Offset
#
# @example
# offset.insert(other) # => ImmutableRelationError raised
#
# @return [undefined]
#
# @raise [ImmutableRelationError]
# raised when inserting into the offset
#
# @api public
def insert(*)
fail ImmutableRelationError, 'inserting into an offset is impossible'
end
# Raise an exception when deleting from the Offset
#
# @example
# offset.delete(other) # => ImmutableRelationError raised
#
# @return [undefined]
#
# @raise [ImmutableRelationError]
# raised when deleting from the offset
#
# @api public
def delete(*)
fail ImmutableRelationError, 'deleting from an offset is impossible'
end
module Methods
# Return a relation with n tuples
#
# @example
# offset_relation = relation.drop(5)
#
# @param [Integer] offset
# the offset of the relation to drop
#
# @return [Offset]
#
# @api public
def drop(offset)
Offset.new(self, offset)
end
end # module Methods
Relation.class_eval { include Methods }
end # class Offset
end # module Operation
end # class Relation
end # module Axiom