Module: Enumerable

Defined in:
lib/errgonomic/core_ext/enumerable.rb

Overview

The all-or-nothing collection, which Rust spells as a collect into Option<Vec> or Result<Vec, E>. On Enumerable rather than Array so it composes with map, and so anything that yields wrappers can be sequenced.

Instance Method Summary collapse

Instance Method Details

#sequence_optionsErrgonomic::Option::Any

Collect an Enumerable of Options into an Option of an Array, stopping at the first None. A member that is not an Option raises unconditionally: with_ambiguous_downstream_errors relaxes what a block returned, not what a caller passed in.

Examples:

[Some(1), Some(2)].sequence_options # => Some([1, 2])
[Some(1), None(), Some(3)].sequence_options # => None()
[].sequence_options # => Some([])

a lazy enumerable is read only as far as the first None

seen = []
lazy = [Some(1), None(), Some(3)].lazy.map { |o| seen << o; o }
lazy.sequence_options # => None()
seen.size # => 2
[Some(1), 2].sequence_options # => raise Errgonomic::TypeMismatchError, "cannot sequence_options Integer; it is not an Option"

a Hash yields pairs, which are Arrays

{ a: Some(1) }.sequence_options # => raise Errgonomic::TypeMismatchError, "cannot sequence_options Array; it is not an Option"

sequence a Hash by its values

{ a: Some(1), b: Some(2) }.values.sequence_options # => Some([1, 2])

Returns:



40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/errgonomic/core_ext/enumerable.rb', line 40

def sequence_options
  values = []
  each do |member|
    unless member.is_a?(Errgonomic::Option::Any)
      raise Errgonomic::TypeMismatchError,
            "cannot sequence_options #{member.class}; it is not an Option"
    end
    return None() if member.none?

    member.tap_some { |value| values << value }
  end
  Some(values)
end

#sequence_resultsErrgonomic::Result::Any

Collect an Enumerable of Results into a Result of an Array, stopping at the first Err, which is returned as it stands so it keeps its error. A member that is not a Result raises on the same terms as sequence_options.

Examples:

[Ok(1), Ok(2)].sequence_results # => Ok([1, 2])
[Ok(1), Err(:nope), Ok(3)].sequence_results # => Err(:nope)
[].sequence_results # => Ok([])

a lazy enumerable is read only as far as the first Err

seen = []
lazy = [Ok(1), Err(:nope), Ok(3)].lazy.map { |r| seen << r; r }
lazy.sequence_results # => Err(:nope)
seen.size # => 2
[Ok(1), Some(2)].sequence_results # => raise Errgonomic::TypeMismatchError, "cannot sequence_results Errgonomic::Option::Some; it is not a Result"

sequence a Hash by its values

{ a: Ok(1), b: Ok(2) }.values.sequence_results # => Ok([1, 2])

Returns:



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/errgonomic/core_ext/enumerable.rb', line 81

def sequence_results
  values = []
  each do |member|
    unless member.is_a?(Errgonomic::Result::Any)
      raise Errgonomic::TypeMismatchError,
            "cannot sequence_results #{member.class}; it is not a Result"
    end
    return member if member.err?

    member.tap_ok { |value| values << value }
  end
  Ok(values)
end