lib/fear/right_biased.rb
# frozen_string_literal: true
module Fear
# @private
module RightBiased
# Performs necessary interface and type checks.
#
module Interface
# Returns the value from this `RightBiased::Right` or the given argument if
# this is a `RightBiased::Left`.
def get_or_else(*args, &block)
Utils.assert_arg_or_block!("get_or_else", *args, &block)
super
end
# Returns this `RightBiased::Right` or the given alternative if
# this is a `RightBiased::Left`.
def or_else(*args, &block)
Utils.assert_arg_or_block!("or_else", *args, &block)
super.tap do |result|
Utils.assert_type!(result, left_class, right_class)
end
end
def flat_map
super.tap do |result|
Utils.assert_type!(result, left_class, right_class)
end
end
# Ensures that returned value either left, or right.
def select(*)
super.tap do |result|
Utils.assert_type!(result, left_class, right_class)
end
end
end
module Right
class << self
def included(base)
base.prepend Interface
end
end
# @overload get_or_else(default)
# @param default [any]
# @return [any] the `#value`.
#
# @overload get_or_else(&default)
# @return [any] the `#value`.
#
def get_or_else(*_args)
value
end
# @return [self]
def or_else
self
end
# @param [any]
# @return [Boolean]
def include?(other_value)
value == other_value
end
# @return [self]
def each
yield(value)
self
end
alias apply each
# Maps the value using given block.
#
# @return [RightBiased::Right]
#
def map
self.class.new(yield(value))
end
# Binds the given function across `RightBiased::Right`.
#
# @return [RightBiased::Left, RightBiased::Right]
#
def flat_map
yield(value)
end
# @return [Option] containing value
def to_option
Some.new(value)
end
# @return [Boolean] true if value satisfies predicate.
def any?
yield(value)
end
# Used in case statement
# @param other [any]
# @return [Boolean]
def ===(other)
if other.is_a?(right_class)
value === other.value
else
super
end
end
end
module Left
prepend Interface
# @!method get_or_else(default)
# @param default [any]
# @return [any] default value
#
# @!method get_or_else(&default)
# @return [any] result of evaluating a block.
#
def get_or_else(*args)
args.fetch(0) { yield }
end
# @!method get_or_else(&alternative)
# @return [RightBiased] result of evaluating a block.
#
def or_else(*_args)
yield
end
# @param [any]
# @return [false]
#
def include?(_value)
false
end
# Ignores the given side-effecting block and return self.
#
# @return [RightBiased::Left]
#
def each
self
end
alias apply each
# Ignores the given block and return self.
#
# @return [RightBiased::Left]
#
def map
self
end
# Ignores the given block and return self.
#
# @return [RightBiased::Left]
#
def flat_map
self
end
# @return [None]
def to_option
None
end
# @return [false]
def any?
false
end
end
end
end