Class: Typisch::Type::Sequence
- Inherits:
-
Constructor
- Object
- Typisch::Type
- Constructor
- Typisch::Type::Sequence
- Defined in:
- lib/typisch/sequence.rb
Overview
A Sequence is an ordered collection of items, all of a given type.
For now if you want an unordered collection, you just have to treat it as an ordered collection with arbitrary order; if you want a map/hash you just treat it as a sequence of tuples. TODO: would be nice to have more of a hierarchy of collection types here, eg OrderedSequence < Set.
(ordered) Sequences support ‘slice types’, which are a kind of structural supertype for sequences. Their use is primarily in specifying partial serializations or partial type-checking for large sequences.
Eg sequence(:integer, :slice => 0…10)
This is saying: “A sequence of ints, which may be of any known length, but where I only care (to validate, serialize, …) at most the first 10 items”.
Eg sequence(:integer, :slice => 0…10, :total_length => false)
This is saying: “A sequence of ints, which may be of any known or unknown length, but where I only care about (validating, serializing, …) at most the first 10 items, and I don’t care about (validating, serializing…) the total length of the collection
Constant Summary collapse
- VALID_IMPLEMENTATION_CLASSES =
I tried allowing any Enumerable, but this resulted in allowing String and a bunch of other things which sort of expose a vaguely-array-like interface but not really in a way that’s helpful for typing purposes. E.g. String in 1.8.7 exposes Enumerable over its lines, but an array-like interface over its characters, sometimes as strings, sometimes as ascii char codes. So not consistent at all.
Any other classes added here must expose Enumerable, but also .length and slices via [] (at least if you want them to work with slice types).
For now allowing Hashes too so they can be typed as a sequence of tuples, although should really only be typed as a set of tuples as there’s no ordering or support for slices.
[::Array, ::Hash]
Constants inherited from Constructor
Constructor::CONSTRUCTOR_TYPE_SUBCLASSES
Instance Attribute Summary collapse
-
#slice ⇒ Object
readonly
Returns the value of attribute slice.
-
#total_length ⇒ Object
readonly
Returns the value of attribute total_length.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Attributes inherited from Typisch::Type
Class Method Summary collapse
Instance Method Summary collapse
- #canonicalize! ⇒ Object
- #check_type(instance, &recursively_check_type) ⇒ Object
-
#initialize(type, options = {}) ⇒ Sequence
constructor
A new instance of Sequence.
- #shallow_check_type(instance) ⇒ Object
- #subexpression_types ⇒ Object
- #tag ⇒ Object
- #to_string(depth, indent) ⇒ Object
- #with_options(options) ⇒ Object
Methods inherited from Constructor
#alternative_types, inherited, #type_lattice
Methods inherited from Typisch::Type
#<, #<=, #<=>, #==, #===, #>, #>=, #alternative_types, #annotations, #annotations=, #excluding_null, #inspect, #recursive?, subtype?, #target, #to_s
Constructor Details
#initialize(type, options = {}) ⇒ Sequence
Returns a new instance of Sequence.
42 43 44 45 46 47 48 49 |
# File 'lib/typisch/sequence.rb', line 42 def initialize(type, ={}) @type = type if [:slice] @slice = [:slice] @slice = (@slice.begin...@slice.end+1) unless @slice.exclude_end? @total_length = [:total_length] != false end end |
Instance Attribute Details
#slice ⇒ Object (readonly)
Returns the value of attribute slice.
51 52 53 |
# File 'lib/typisch/sequence.rb', line 51 def slice @slice end |
#total_length ⇒ Object (readonly)
Returns the value of attribute total_length.
51 52 53 |
# File 'lib/typisch/sequence.rb', line 51 def total_length @total_length end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
91 92 93 |
# File 'lib/typisch/sequence.rb', line 91 def type @type end |
Class Method Details
.check_subtype(x, y, &recursively_check_subtype) ⇒ Object
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/typisch/sequence.rb', line 30 def check_subtype(x, y, &recursively_check_subtype) recursively_check_subtype[x.type, y.type] && ( !x.slice || (y.slice && ( x.slice.begin <= y.slice.begin && x.slice.end >= y.slice.end && (x.total_length || !y.total_length) )) ) end |
.top_type(overall_top) ⇒ Object
26 27 28 |
# File 'lib/typisch/sequence.rb', line 26 def top_type(overall_top) new(overall_top, :slice => (0...0), :total_length => false) end |
Instance Method Details
#canonicalize! ⇒ Object
102 103 104 |
# File 'lib/typisch/sequence.rb', line 102 def canonicalize! @type = @type.target end |
#check_type(instance, &recursively_check_type) ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/typisch/sequence.rb', line 61 def check_type(instance, &recursively_check_type) shallow_check_type(instance) && if @slice (instance[@slice] || []).all? {|i| recursively_check_type[@type, i]} && (!@total_length || ::Integer === instance.length) else instance.all? {|i| recursively_check_type[@type, i]} end end |
#shallow_check_type(instance) ⇒ Object
83 84 85 |
# File 'lib/typisch/sequence.rb', line 83 def shallow_check_type(instance) case instance when *VALID_IMPLEMENTATION_CLASSES then true else false end end |
#subexpression_types ⇒ Object
57 58 59 |
# File 'lib/typisch/sequence.rb', line 57 def subexpression_types [@type] end |
#tag ⇒ Object
87 88 89 |
# File 'lib/typisch/sequence.rb', line 87 def tag "Sequence" end |
#to_string(depth, indent) ⇒ Object
93 94 95 96 97 98 99 100 |
# File 'lib/typisch/sequence.rb', line 93 def to_string(depth, indent) result = "sequence(#{@type.to_s(depth+1, indent)}" if @slice result << ", :slice => #{@slice}" result << ", :total_length => false" unless @total_length end result << ")" end |
#with_options(options) ⇒ Object
53 54 55 |
# File 'lib/typisch/sequence.rb', line 53 def () self.class.new(@type, {:slice => @slice, :total_length => @total_length}.merge!()) end |