Class: NRSER::Types::Combinator
- Defined in:
- lib/nrser/types/combinators.rb
Overview
Abstract base class for logically combining types to create new ones.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#types ⇒ Array<NRSER::Types::Type>
readonly
The parametrized types, in the order they will be tested.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#custom_from_s(s) ⇒ Object
Parse a satisfying value from a String or raise a NRSER::TypeError.
- #explain ⇒ Object
-
#from_data(data) ⇒ Object
Overridden to.
- #has_from_data? ⇒ Boolean
-
#has_from_s? ⇒ Boolean
Overridden to delegate functionality to the combined types.
-
#has_to_data? ⇒ Boolean
Overridden to delegate functionality to the combined types:.
-
#initialize(*types, **options) ⇒ Combinator
constructor
A new instance of Combinator.
-
#to_data(value) ⇒ Object
Overridden to delegate functionality to the combined types:.
Methods inherited from Type
#===, #builtin_inspect, #check, #check!, #from_s, #inspect, #intersection, #name, #not, #respond_to?, #test, #test?, #to_s, #union, #xor
Constructor Details
#initialize(*types, **options) ⇒ Combinator
Returns a new instance of Combinator.
20 21 22 23 |
# File 'lib/nrser/types/combinators.rb', line 20 def initialize *types, ** super ** @types = types.map { |type| NRSER::Types.make type } end |
Instance Attribute Details
#types ⇒ Array<NRSER::Types::Type> (readonly)
The parametrized types, in the order they will be tested.
17 18 19 |
# File 'lib/nrser/types/combinators.rb', line 17 def types @types end |
Instance Method Details
#==(other) ⇒ Object
167 168 169 170 171 |
# File 'lib/nrser/types/combinators.rb', line 167 def == other equal?(other) || ( other.class == self.class && other.types == @types ) end |
#custom_from_s(s) ⇒ Object
Parse a satisfying value from a String or raise a NRSER::TypeError.
If this type has it’s own ‘@from_s` that was provided via the `from_s:` keyword at construction, then that and only that is always used
-
the type will never try any of the combined types’ ‘#from_s`.
It’s considered the way to parse a string into a value that satisfies the type. If it fails, a NRSER::TypeError will be raised (or any error the ‘@from_s` proc itself raises before we get to checking it).
If the type doesn’t have it’s own ‘@from_s`, each of the combined types’ ‘#from_s` will be tried in sequence, and the first value that satisfies the combined type will be returned.
This is obviously much less efficient, but provides a nice automatic mechanism for parsing from strings for combined types. If none of the combined types’ ‘#from_s` succeed (or if there are none) a NRSER::TypeError is raised.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/nrser/types/combinators.rb', line 68 def custom_from_s s unless @from_s.nil? return check @from_s.call( s ) end @types.each { |type| if type.has_from_s? begin return check type.from_s(s) rescue TypeError => e # pass end end } raise TypeError, "none of combinator #{ self.to_s } types could convert #{ s.inspect }" end |
#explain ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/nrser/types/combinators.rb', line 26 def explain if self.class::JOIN_SYMBOL NRSER::Types::L_PAREN + # ' ' + @types.map { |type| type.explain }.join( self.class::JOIN_SYMBOL ) + # ' ' + NRSER::Types::R_PAREN else "#{ self.class.demod_name }<" + @types.map { |type| type.explain }.join( ',' ) + ">" end end |
#from_data(data) ⇒ Object
Overridden to
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/nrser/types/combinators.rb', line 111 def from_data data unless has_from_data? raise NoMethodError, "#from_data not defined" end errors = [] types.each do |type| if type.has_from_data? begin return check!( type.from_data data ) rescue StandardError => error errors << error end end end raise NRSER::MultipleErrors.new \ errors, headline: "No type successfully loaded data" end |
#has_from_data? ⇒ Boolean
105 106 107 |
# File 'lib/nrser/types/combinators.rb', line 105 def has_from_data? @types.any? { |type| type.has_from_data? } end |
#has_from_s? ⇒ Boolean
Overridden to delegate functionality to the combined types.
A combinator may attempt to parse from a string if:
-
It has it’s own ‘@from_s` provided at construction.
-
Any of it’s combined types can parse from a string.
See Type#from_s for details of how it actually happens.
100 101 102 |
# File 'lib/nrser/types/combinators.rb', line 100 def has_from_s? !@from_s.nil? || @types.any? { |type| type.has_from_s? } end |
#has_to_data? ⇒ Boolean
Overridden to delegate functionality to the combined types:
A combinator can convert a value to data if any of it’s types can.
140 141 142 |
# File 'lib/nrser/types/combinators.rb', line 140 def has_to_data? @types.any? { |type| type.has_to_data? } end |
#to_data(value) ⇒ Object
Overridden to delegate functionality to the combined types:
The first of the combined types that responds to ‘#to_data` is used to dump the value.
156 157 158 159 160 161 162 163 164 |
# File 'lib/nrser/types/combinators.rb', line 156 def to_data value @types.each { |type| if type.has_to_data? return type.to_data value end } raise NoMethodError, "#to_data not defined" end |