Class: UnionType
- Includes:
- Enumerable
- Defined in:
- lib/union_type/union_type.rb,
lib/union_type/version.rb
Overview
A union type that matches values belonging to any of its member classes.
Member classes are stored in a SortedSet sorted alphabetically by name. Redundant subclasses are dropped automatically: if a superclass is already present, its subclasses add no information and are removed.
Constant Summary collapse
- VERSION =
The current gem version.
"0.1.1"
Class Method Summary collapse
-
.[](*classes) ⇒ UnionType
Creates a frozen UnionType from the given classes.
Instance Method Summary collapse
-
#&(other) ⇒ UnionType?
Returns a new UnionType containing only classes matched by both unions, keeping the more specific class when one is a subclass of the other.
-
#==(other) ⇒ Boolean
(also: #eql?)
Value equality: two unions are equal when they contain the same classes.
-
#===(value) ⇒ Boolean
Returns
trueifvalueis an instance of any member class. -
#cover?(klass) ⇒ Boolean
Returns
trueif this union coversklass— i.e. -
#each {|klass| ... } ⇒ self
Yields each member class in sorted (alphabetical) order.
-
#hash ⇒ Integer
Hash consistent with #eql?, for use as a Hash key.
-
#initialize(*classes) ⇒ UnionType
constructor
A new instance of UnionType.
-
#inspect ⇒ String
(also: #to_s)
Human-readable representation, e.g.
-
#types ⇒ SortedSet
The underlying SortedSet of internal entry objects.
-
#|(other) ⇒ UnionType
Returns a new UnionType that is the union of
selfandother.
Constructor Details
#initialize(*classes) ⇒ UnionType
Returns a new instance of UnionType.
50 51 52 53 54 55 56 |
# File 'lib/union_type/union_type.rb', line 50 def initialize(*classes) raise ArgumentError, "requires at least one class" if classes.empty? minimal = classes.reject { |c| classes.any? { |other| c != other && c < other } } @types = SortedSet.new(minimal.map { Entry.new(_1) }).freeze freeze end |
Class Method Details
Instance Method Details
#&(other) ⇒ UnionType?
Returns a new UnionType containing only classes matched by both unions, keeping the more specific class when one is a subclass of the other. Returns nil when the intersection is empty.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/union_type/union_type.rb', line 132 def &(other) other_types = case other when UnionType then other.to_a when Class then [other] else raise TypeError, "expected Class or UnionType, got #{other.class}" end classes = flat_map { |a| other_types.filter_map { |b| if a == b || a < b then a elsif b < a then b end } }.uniq UnionType.new(*classes) unless classes.empty? end |
#==(other) ⇒ Boolean Also known as: eql?
Value equality: two unions are equal when they contain the same classes. Argument order does not matter.
155 156 157 |
# File 'lib/union_type/union_type.rb', line 155 def ==(other) other.class == UnionType && to_a == other.to_a end |
#===(value) ⇒ Boolean
Returns true if value is an instance of any member class. This makes UnionType work in case/when expressions.
76 77 78 |
# File 'lib/union_type/union_type.rb', line 76 def ===(value) any? { _1 === value } end |
#cover?(klass) ⇒ Boolean
Returns true if this union covers klass — i.e. klass is a member or a subclass of a member.
98 99 100 |
# File 'lib/union_type/union_type.rb', line 98 def cover?(klass) any? { klass <= _1 } end |
#each {|klass| ... } ⇒ self
Yields each member class in sorted (alphabetical) order. Required by Enumerable; enables #to_a, #map, #include?, etc.
63 64 65 |
# File 'lib/union_type/union_type.rb', line 63 def each(&block) @types.each { block.call(_1.klass) } end |
#hash ⇒ Integer
Returns hash consistent with #eql?, for use as a Hash key.
161 162 163 |
# File 'lib/union_type/union_type.rb', line 161 def hash to_a.hash end |
#inspect ⇒ String Also known as: to_s
Returns human-readable representation, e.g. UnionType(Integer | String).
166 167 168 |
# File 'lib/union_type/union_type.rb', line 166 def inspect "UnionType(#{map(&:name).join(" | ")})" end |
#types ⇒ SortedSet
The underlying SortedSet of internal entry objects. Entries are sorted by class name; use #to_a to get plain Class objects.
84 85 86 |
# File 'lib/union_type/union_type.rb', line 84 def types @types end |
#|(other) ⇒ UnionType
Returns a new UnionType that is the union of self and other. Redundant subclasses are removed as in new.
112 113 114 115 116 117 118 |
# File 'lib/union_type/union_type.rb', line 112 def |(other) case other when Class then UnionType.new(*self, other) when UnionType then UnionType.new(*self, *other) else raise TypeError, "expected Class or UnionType, got #{other.class}" end end |