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
24 changes: 24 additions & 0 deletions lib/errgonomic/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module Option
# The base class for all options. Some and None are subclasses.
#
class Any
include Comparable

# def method_missing(_name, *_args)
# raise 'do it right noob'
# end
Expand Down Expand Up @@ -50,6 +52,28 @@ def deconstruct
[Errgonomic::Option::None]
end

# Options order like Rust's: None sorts before any Some, and Somes
# order by their inner values. Follows Ruby's <=> convention of
# returning nil for incomparable operands, whether the other object is
# not an Option or the inner values do not themselves compare.
#
# @example
# (Some(5) <=> Some(6)) # => -1
# (None() <=> Some(5)) # => -1
# (Some(5) <=> None()) # => 1
# (None() <=> None()) # => 0
# (Some(1) <=> Some("x")) # => nil
# (Some(1) <=> 1) # => nil
# [Some(2), None(), Some(1)].sort # => [None(), Some(1), Some(2)]
# [Some(2), Some(1)].min # => Some(1)
def <=>(other)
return nil unless other.is_a?(Errgonomic::Option::Any)
return none? ? 0 : 1 if other.none?
return -1 if none?

value <=> other.value
end

# return true if the contained value is Some and the block returns truthy
#
# @example
Expand Down
21 changes: 21 additions & 0 deletions lib/errgonomic/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,33 @@ module Result
# much logic as possible here, and let Ok and Err handle their
# initialization and self identification.
class Any
include Comparable

attr_reader :value

def initialize(value)
@value = value
end

# Results order like Rust's: Ok sorts before any Err, and same variants
# order by their inner values. Follows Ruby's <=> convention of
# returning nil for incomparable operands, whether the other object is
# not a Result or the inner values do not themselves compare.
#
# @example
# (Ok(1) <=> Ok(2)) # => -1
# (Ok(1) <=> Err(:a)) # => -1
# (Err(:a) <=> Ok(1)) # => 1
# (Err(:a) <=> Err(:b)) # => -1
# (Ok(1) <=> 1) # => nil
# [Err(:a), Ok(2), Ok(1)].sort # => [Ok(1), Ok(2), Err(:a)]
def <=>(other)
return nil unless other.is_a?(Errgonomic::Result::Any)
return ok? ? -1 : 1 if self.class != other.class

value <=> other.value
end

# Equality comparison for Result objects is based on value not reference.
#
# @param other [Object]
Expand Down
Loading