Class: Qrb::TupleType

Inherits:
Type
  • Object
show all
Defined in:
lib/qrb/type/tuple_type.rb

Overview

The Tuple type generator allows capturing information facts. For instance, a Point type could be defined as follows:

Point = {r: Length, theta: Angle}

This class allows capturing those information types, as in:

Length = BuiltinType.new(Fixnum)
Angle  = BuiltinType.new(Float)
Point  = TupleType.new(Heading.new([
           Attribute.new(:r, Length),
           Attribute.new(:theta, Angle)
         ]))

A Hash with Symbol as keys is used as concrete ruby representation for tuples. The values map to the concrete representations of each attribute type:

R(Point) = Hash[r: R(Length), theta: R(Angle)]
         = Hash[r: Fixnum, theta: Float]

Accordingly, the ‘dress` transformation function has the signature below. It expects it’s Alpha/Object argument to be a Hash with all and only the expected keys (either as Symbols or Strings). The ‘dress` function applies on every attribute value according to their respective type.

dress :: Alpha  -> Point                         throws TypeError
dress :: Object -> Hash[r: Fixnum, theta: Float] throws TypeError

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Type

#name, #name=, #to_s

Constructor Details

#initialize(heading, name = nil) ⇒ TupleType

Returns a new instance of TupleType.



34
35
36
37
38
39
40
41
# File 'lib/qrb/type/tuple_type.rb', line 34

def initialize(heading, name = nil)
  unless heading.is_a?(Heading)
    raise ArgumentError, "Heading expected, got `#{heading}`"
  end

  super(name)
  @heading = heading
end

Instance Attribute Details

#headingObject (readonly)

Returns the value of attribute heading.



42
43
44
# File 'lib/qrb/type/tuple_type.rb', line 42

def heading
  @heading
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



88
89
90
91
# File 'lib/qrb/type/tuple_type.rb', line 88

def ==(other)
  return false unless other.is_a?(TupleType)
  heading == other.heading
end

#default_nameObject



44
45
46
# File 'lib/qrb/type/tuple_type.rb', line 44

def default_name
  "{#{heading.to_name}}"
end

#dress(value, handler = DressHelper.new) ⇒ Object

Convert ‘value` (supposed to be Hash) to a Tuple, by checking attributes and applying `dress` on them in turn. Raise an error if any attribute is missing or unrecognized, as well as if any sub transformation fails.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/qrb/type/tuple_type.rb', line 62

def dress(value, handler = DressHelper.new)
  handler.failed!(self, value) unless value.is_a?(Hash)

  # Uped values, i.e. tuple under construction
  uped = {}

  # Check the tuple arity and fail fast if extra attributes
  # (missing attributes are handled just after)
  if value.size > heading.size
    extra = value.keys.map(&:to_s) - heading.map{|attr| attr.name.to_s }
    handler.fail!("Unrecognized attribute `#{extra.first}`")
  end

  # Up each attribute in turn now. Fail on missing ones.
  heading.each do |attribute|
    val = attribute.fetch_on(value) do
      handler.fail!("Missing attribute `#{attribute.name}`")
    end
    handler.deeper(attribute.name) do
      uped[attribute.name] = attribute.type.dress(val, handler)
    end
  end

  uped
end

#hashObject



94
95
96
# File 'lib/qrb/type/tuple_type.rb', line 94

def hash
  self.class.hash ^ heading.hash
end

#include?(value) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
57
# File 'lib/qrb/type/tuple_type.rb', line 48

def include?(value)
  return false unless value.is_a?(Hash)
  return false if value.size > heading.size
  heading.all? do |attribute|
    attr_val = value.fetch(attribute.name){
      return false
    }
    attribute.type.include?(attr_val)
  end
end