Module: Plumb::Equality
- Defined in:
- lib/plumb/composable.rb
Overview
Override #=== and #== for Composable instances. but only when included in classes, not extended.
Instance Method Summary collapse
-
#<(other) ⇒ Object
Strict subtype / supertype.
-
#<=(other) ⇒ Boolean
Subtype/subset operator.
-
#==(other) ⇒ Boolean
Compares nodes by exact class and children.
-
#===(other) ⇒ Boolean
#===equality. - #>(other) ⇒ Object
-
#>=(other) ⇒ Object
selfis a supertype ofother: every value ofotheris a value ofself. -
#subtype_of?(other) ⇒ Boolean
Leaf hook for Plumb::Subtyping.subtype?, called once the algebra (Intersection/Or/top, and the #subtype_identity projection that replaces a converting node with what it produces) has been peeled away.
-
#supertype_of?(other) ⇒ Boolean
Mirror of #subtype_of?, for relations the supertype owns and the subtype can't know about (eg. Interface duck-typing: any type is a subtype of an Interface whose methods its values support).
Instance Method Details
#<(other) ⇒ Object
Strict subtype / supertype.
151 |
# File 'lib/plumb/composable.rb', line 151 def <(other) = (self <= other) && !(self >= other) |
#<=(other) ⇒ Boolean
Subtype/subset operator. a <= b is true when every value described by
self is also described by other (other may be a raw Ruby class or
value; it is normalized). Delegates to the generic Plumb::Subtyping engine.
140 141 142 |
# File 'lib/plumb/composable.rb', line 140 def <=(other) Plumb::Subtyping.subtype?(self, other) end |
#==(other) ⇒ Boolean
Compares nodes by exact class and children. Use instance_of?, not is_a?:
a subclass may change behavior without changing #children, making parent/subclass
equality asymmetric. Subtyping and optimization short-circuit on ==, so that
asymmetry could discard the narrower node before its behavioral guards run.
131 132 133 |
# File 'lib/plumb/composable.rb', line 131 def ==(other) other.instance_of?(self.class) && other.respond_to?(:children) && other.children == children end |
#===(other) ⇒ Boolean
#=== equality. So that Plumb steps can be used in case statements and pattern matching.
116 117 118 119 120 121 122 123 |
# File 'lib/plumb/composable.rb', line 116 def ===(other) case other when Composable other == self else resolve(other).valid? end end |
#>(other) ⇒ Object
152 |
# File 'lib/plumb/composable.rb', line 152 def >(other) = (self >= other) && !(self <= other) |
#>=(other) ⇒ Object
self is a supertype of other: every value of other is a value of
self.
146 147 148 |
# File 'lib/plumb/composable.rb', line 146 def >=(other) Plumb::Subtyping.subtype?(Composable.wrap(other), self) end |
#subtype_of?(other) ⇒ Boolean
Leaf hook for Plumb::Subtyping.subtype?, called once the algebra (Intersection/Or/top, and the #subtype_identity projection that replaces a converting node with what it produces) has been peeled away. It must NOT delegate back to #<= (that would recurse); it recurses only through Plumb::Subtyping.subtype?.
Default behaviour:
1. reflexive structural equality;
2. atomic leaves (a single raw matcher/value) compared via Ruby
semantics (Plumb::Subtyping.atomic_subtype?);
3. covariant containers — same class with pairwise-subtype children,
which covers Array/Tuple/HashMap/Stream and any custom container that
exposes #children, for free.
Override for bespoke leaf relations (see HashClass width/depth subtyping).
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/plumb/composable.rb', line 171 def subtype_of?(other) return true if self == other if Plumb::Subtyping.atomic?(self) && Plumb::Subtyping.atomic?(other) # #children contains only the matcher, but a refinement also describes its # base. Check both or an unrelated atomic value may pass on matcher overlap # alone (for example, Value[5.0] against Integer[1..5]). if other.respond_to?(:base) && other.base && !Plumb::Subtyping.subtype?(self, other.base) return false end return Plumb::Subtyping.atomic_subtype?(children.first, other.children.first) end return false unless other.instance_of?(self.class) return false if children.empty? || children.size != other.children.size children.zip(other.children).all? { |c, o| Plumb::Subtyping.subtype?(c, o) } end |
#supertype_of?(other) ⇒ Boolean
Mirror of #subtype_of?, for relations the supertype owns and the subtype can't know about (eg. Interface duck-typing: any type is a subtype of an Interface whose methods its values support). Consulted by Plumb::Subtyping.subtype? only after #subtype_of? declines. Default: no — only the subtype side decides. Recurse via Plumb::Subtyping.subtype?, never #<=. Override for bespoke supertype behaviour (see InterfaceClass).
199 |
# File 'lib/plumb/composable.rb', line 199 def supertype_of?(other) = false |