dry-monads icon indicating copy to clipboard operation
dry-monads copied to clipboard

`Try::Error` has an incorrect `deconstruct` implementation

Open alexkalderimis opened this issue 7 months ago • 0 comments

Describe the bug

The following code should work:

case Try { n / d }
in Value(x)
  puts "n / d = #{x}"
in Error(ZeroDivisionError => ex)
  puts "divisor must not be zero"
else [x]
  puts "Got exception: #{x}"
end

But it does not - because Try implements deconstruct from RightBiased, which expects the value to be stored at the @value instance variable.

Try::Error does not have a @value variable - it uses @exception instead. Thus pattern matching on Error values never has the expected results.

Current workarounds: call #to_result.

To Reproduce

res = Try { 3 / 2 }
err = Try { 1 / 0 }

# Value works fine
res => Value(x)
puts x # => 1

# Error succeeds on pattern match
err => Try::Error(ex)

# But binds ex to nil, and ex != err.exception
puts ex.inspect => nil
puts err.exception => #<ZeroDivisionError: divided by 0>

# Workaround
err.to_result => Failure(ex)
puts ex.inspect => #<ZeroDivisionError: divided by 0>

Expected behavior

Pattern matching on Try::Error values should bind the exception.

My environment

  • Affects my production application: YES - workarounds are available
  • Ruby version: ALL (strictly speaking >= 3.0)
  • OS: ALL

alexkalderimis avatar Jul 22 '24 23:07 alexkalderimis