Class: Plumb::Result
- Inherits:
-
Object
- Object
- Plumb::Result
- Defined in:
- lib/plumb/result.rb
Overview
The value + validity + errors triple that flows through a composition.
There are two ways to derive one result from another:
- #valid / #invalid ALLOCATE a fresh Result and leave the receiver
untouched. This is the safe, functional form: use it in custom types, and
anywhere a result may outlive the call or be captured (Streams close over
it lazily; concurrent Arrays hand results between threads). This is the
public API for user-defined steps.
- #valid! / #invalid! FLIP THE RECEIVER in place and return it (no
allocation). Plumb's own built-in steps use these on the hot path to
avoid a Result per node — but only where the input cursor is theirs to
mutate: never on a shared/constant Result, never when the result escapes
into a closure or another thread. The one fork point (Or) snapshots the
value and #resets before retrying its second branch.
So built-ins stay allocation-lean while user code (and the concurrency- and laziness-sensitive built-ins) keep the footgun-free copying semantics, at the cost of a few extra allocations there.
Valid and Invalid were once separate subclasses; collapsing them into one class with a boolean is what makes the in-place valid<->invalid flip possible (Ruby can't change an object's class).
Instance Attribute Summary collapse
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#value ⇒ Object
readonly
Returns the value of attribute value.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(value, valid: true, errors: nil) ⇒ Result
constructor
A new instance of Result.
- #inspect ⇒ Object
- #invalid(val = value, errors: nil) ⇒ Object
- #invalid!(val = value, errors: nil) ⇒ Object
- #invalid? ⇒ Boolean
- #map(callable) ⇒ Object
-
#reset(val) ⇒ Object
Reset the cursor to a fresh VALID state carrying
val, in place. -
#valid(val = value) ⇒ Object
Allocating, copy-returning form.
-
#valid!(val = value) ⇒ Object
In-place form: flip THIS result and return self.
- #valid? ⇒ Boolean
Constructor Details
#initialize(value, valid: true, errors: nil) ⇒ Result
Returns a new instance of Result.
47 48 49 50 51 |
# File 'lib/plumb/result.rb', line 47 def initialize(value, valid: true, errors: nil) @value = value @valid = valid @errors = errors end |
Instance Attribute Details
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
45 46 47 |
# File 'lib/plumb/result.rb', line 45 def errors @errors end |
#value ⇒ Object (readonly)
Returns the value of attribute value.
45 46 47 |
# File 'lib/plumb/result.rb', line 45 def value @value end |
Class Method Details
.invalid(value = nil, errors: nil) ⇒ Object
34 35 36 |
# File 'lib/plumb/result.rb', line 34 def invalid(value = nil, errors: nil) new(value, valid: false, errors:) end |
.valid(value = nil) ⇒ Object
30 31 32 |
# File 'lib/plumb/result.rb', line 30 def valid(value = nil) new(value, valid: true) end |
.wrap(value) ⇒ Object
38 39 40 41 42 |
# File 'lib/plumb/result.rb', line 38 def wrap(value) return value if value.is_a?(Result) valid(value) end |
Instance Method Details
#inspect ⇒ Object
56 57 58 |
# File 'lib/plumb/result.rb', line 56 def inspect %(<#{self.class}##{object_id} valid:#{@valid} value:#{value.inspect} errors:#{errors.inspect}>) end |
#invalid(val = value, errors: nil) ⇒ Object
65 66 67 |
# File 'lib/plumb/result.rb', line 65 def invalid(val = value, errors: nil) Result.invalid(val, errors:) end |
#invalid!(val = value, errors: nil) ⇒ Object
78 79 80 81 82 83 |
# File 'lib/plumb/result.rb', line 78 def invalid!(val = value, errors: nil) @value = val @valid = false @errors = errors self end |
#invalid? ⇒ Boolean
54 |
# File 'lib/plumb/result.rb', line 54 def invalid? = !@valid |
#map(callable) ⇒ Object
92 93 94 |
# File 'lib/plumb/result.rb', line 92 def map(callable) @valid ? callable.call(self) : self end |
#reset(val) ⇒ Object
Reset the cursor to a fresh VALID state carrying val, in place. The
mutating scratch-reuse primitive behind the HashClass/ArrayClass element
loops (same as #valid!(val)).
88 89 90 |
# File 'lib/plumb/result.rb', line 88 def reset(val) valid!(val) end |
#valid(val = value) ⇒ Object
Allocating, copy-returning form. Safe everywhere: the receiver is untouched.
61 62 63 |
# File 'lib/plumb/result.rb', line 61 def valid(val = value) Result.valid(val) end |
#valid!(val = value) ⇒ Object
In-place form: flip THIS result and return self. No allocation. Only for code that owns the cursor (see the class docstring).
71 72 73 74 75 76 |
# File 'lib/plumb/result.rb', line 71 def valid!(val = value) @value = val @valid = true @errors = nil self end |
#valid? ⇒ Boolean
53 |
# File 'lib/plumb/result.rb', line 53 def valid? = @valid |