Class: Plumb::Or
- Inherits:
-
Object
- Object
- Plumb::Or
- Includes:
- Composable, Disjunction
- Defined in:
- lib/plumb/or.rb
Overview
LEFT-BIASED CHOICE — try left, fall back to right, built by
Composable#| when some branch changes the value. The all-branches-preserving
case (a genuine set union) is Union; see Disjunction.
A choice's ends differ, because a converting branch accepts an input the join
of the outputs would reject: Integer | String.transform(:to_i) consumes
Integer | String and produces Integer | Integer.
Instance Attribute Summary
Attributes included from Disjunction
Instance Method Summary collapse
-
#output_type ⇒ Object
(A | B).output_type == A.output_type | B.output_type.
-
#value_preserving? ⇒ Boolean
A disjunction preserves the value only if EVERY branch does — a branch that transforms (a coercion) changes it when taken.
Methods included from Disjunction
build, #call, #initialize, #input_type, merge_errors, #with_children
Methods included from Composable
#&, #/, #>>, #[], #absorb_input, #absorb_output, #accepted_type, #as_node, #build, #check, #children, #defer, #fusable_step?, #fuse_with, #generate, #idempotent?, included, #input_type, #invalid, #invoke, #match, #metadata, #not, #pipeline, #policy, resolve_operand, #static, #subtype_identity, #to_json_schema, #to_mermaid, #to_plumb_type, #to_s, #transform, #value, #where, #with, wrap, #|
Methods included from Callable
Instance Method Details
#output_type ⇒ Object
(A | B).output_type == A.output_type | B.output_type. A converting branch produces something other than what it consumed, so this genuinely has to map over the branches — which is exactly what Union does NOT have to do. #input_type is shared with Union; see Disjunction#input_type.
22 23 24 25 26 |
# File 'lib/plumb/or.rb', line 22 def output_type l = @left.output_type r = @right.output_type l.equal?(@left) && r.equal?(@right) ? self : Disjunction.build(l, r) end |
#value_preserving? ⇒ Boolean
A disjunction preserves the value only if EVERY branch does — a branch that transforms (a coercion) changes it when taken. Recurses through the cached accessor so shared subtrees are memoized once.
Kept computed rather than hardcoded false: Disjunction.build only routes the
converting case here, but Or.new remains callable directly (the Decorator
rebuilds by class), so an Or may still hold two preserving branches.
35 |
# File 'lib/plumb/or.rb', line 35 def value_preserving? = children.all? { |c| Plumb::Subtyping.value_preserving?(c) } |