Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/errgonomic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ class NotPresentError < Error; end
class TypeMismatchError < Error; end

class UnwrapError < Error
def initialize(msg, value)
attr_reader :value

def initialize(msg, value = nil)
super(msg)
@value = value
end
Expand All @@ -47,8 +49,9 @@ class NotComparableError < StandardError; end
class SerializeError < TypeError; end

# A little bit of control over how pedantic we are in our runtime type checks.
# Default is false: we are pedantic and raise errors on type mismatches.
def self.give_me_ambiguous_downstream_errors?
@give_me_ambiguous_downstream_errors || true
!!@give_me_ambiguous_downstream_errors
end

# You can opt out of the pedantic runtime checks for lazy block evaluation,
Expand Down
13 changes: 7 additions & 6 deletions lib/errgonomic/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def or_else(&block)
return self if some?

val = block.call
if !val.is_a?(Errgonomic::Option::Any) && Errgonomic.give_me_ambiguous_downstream_errors?
if !val.is_a?(Errgonomic::Option::Any) && !Errgonomic.give_me_ambiguous_downstream_errors?
raise Errgonomic::ArgumentError.new, "block must return an Option, was #{val.class.name}"
end

Expand All @@ -275,16 +275,17 @@ def and(other)
other
end

# If self is Some, call the given block and return its value. Block most return an Option.
# If self is Some, call the given block with the inner value and return
# its result. Block must return an Option.
#
# @example
# None().and_then { Some(1) } # => None()
# Some(2).and_then { Some(3) } # => Some(3)
# None().and_then { |x| Some(x + 1) } # => None()
# Some(2).and_then { |x| Some(x + 1) } # => Some(3)
def and_then(&block)
return self if none?

val = block.call
if Errgonomic.give_me_ambiguous_downstream_errors? && !val.is_a?(Errgonomic::Option::Any)
val = block.call(value)
if !Errgonomic.give_me_ambiguous_downstream_errors? && !val.is_a?(Errgonomic::Option::Any)
raise Errgonomic::ArgumentError.new, "block must return an Option, was #{val.class.name}"
end

Expand Down
19 changes: 8 additions & 11 deletions lib/errgonomic/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def and_then(&block)
return self if err?

res = block.call(value)
if !res.is_a?(Errgonomic::Result::Any) && Errgonomic.give_me_ambiguous_downstream_errors?
if !res.is_a?(Errgonomic::Result::Any) && !Errgonomic.give_me_ambiguous_downstream_errors?
raise Errgonomic::ArgumentError, 'and_then block must return a Result'
end

Expand Down Expand Up @@ -173,20 +173,18 @@ def or(other)
# Sorry about that, hopefully it helps your tests. Better than ambiguous
# downstream "undefined method" errors, probably.
#
# TODO yield the Err
#
# @param block [Proc]
#
# @example
# Ok(1).or_else { Ok(2) } # => Ok(1)
# Err(:o).or_else { Ok(1) } # => Ok(1)
# Err(:q).or_else { Err(:r) } # => Err(:r)
# Err(:s).or_else { "oops" } # => raise Errgonomic::ArgumentError, "or_else block must return a Result"
# Ok(1).or_else { |e| Ok(2) } # => Ok(1)
# Err(:o).or_else { |e| Ok(1) } # => Ok(1)
# Err(:q).or_else { |e| Err(:r) } # => Err(:r)
# Err(:s).or_else { |e| "oops" } # => raise Errgonomic::ArgumentError, "or_else block must return a Result"
def or_else(&block)
return self if ok?

res = block.call(self)
if !res.is_a?(Errgonomic::Result::Any) && Errgonomic.give_me_ambiguous_downstream_errors?
res = block.call(value)
if !res.is_a?(Errgonomic::Result::Any) && !Errgonomic.give_me_ambiguous_downstream_errors?
raise Errgonomic::ArgumentError, 'or_else block must return a Result'
end

Expand Down Expand Up @@ -249,8 +247,7 @@ def tap_ok(&block)
def map(&block)
return self if err?

@value = block.call(value)
self
Ok(block.call(value))
end

# Refuse to serialize an unwrapped Result as a String. Results must be
Expand Down
Loading