Class: Concurrent::Maybe
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
|
|
Instance Chain:
self,
Comparable,
Synchronization::Object ,
Synchronization::Volatile ,
Synchronization::AbstractObject
|
|
Inherits: | Concurrent::Synchronization::Object |
Defined in: | lib/concurrent-ruby/concurrent/maybe.rb |
Overview
A Maybe
encapsulates an optional value. A Maybe
either contains a value of (represented as Just
), or it is empty (represented as Nothing
). Using Maybe
is a good way to deal with errors or exceptional cases without resorting to drastic measures such as exceptions.
Maybe
is a replacement for the use of nil
with better type checking.
For compatibility with Concern::Obligation
the predicate and accessor methods are aliased as #fulfilled?, #rejected?, #value, and #reason.
Motivation
A common pattern in languages with pattern matching, such as Erlang and Haskell, is to return either a value or an error from a function Consider this Erlang code:
“‘erlang case file:consult(“data.dat”) of
{ok, Terms} -> do_something_useful(Terms);
{error, Reason} -> lager:error(Reason)
end. “‘
In this example the standard library function consult returns a tuple with two elements: an atom (similar to a ruby symbol) and a variable containing ancillary data. On success it returns the atom ok
and the data from the file. On failure it returns error
and a string with an explanation of the problem. With this pattern there is no ambiguity regarding success or failure. If the file is empty the return value cannot be misinterpreted as an error. And when an error occurs the return value provides useful information.
In Ruby we tend to return nil
when an error occurs or else we raise an exception. Both of these idioms are problematic. Returning nil
is ambiguous because nil
may also be a valid value. It also lacks information pertaining to the nature of the error. Raising an exception is both expensive and usurps the normal flow of control. All of these problems can be solved with the use of a Maybe
.
A Maybe
is unambiguous with regard to whether or not it contains a value. When Just
it contains a value, when Nothing
it does not. When Just
the value it contains may be nil
, which is perfectly valid. When Nothing
the reason for the lack of a value is contained as well. The previous Erlang example can be duplicated in Ruby in a principled way by having functions return Maybe
objects:
“‘ruby result = MyFileUtils.consult
(“data.dat”) # returns a Maybe if result.just?
do_something_useful(result.value) # or result.just
else
logger.error(result.reason) # or result.nothing
end “‘
Constant Summary
-
NONE =
::Object.new.freeze
Class Attribute Summary
Synchronization::Object
- Inherited
Class Method Summary
-
.from(*args) {|args| ... } ⇒ Maybe
Create a new
Maybe
using the given block. -
.just(value) ⇒ Maybe
Create a new
Just
with the given value. -
.nothing(error = '') ⇒ Maybe
Create a new
Nothing
with the given (optional) reason. -
.new(just, nothing) ⇒ Maybe
constructor
private
Create a new
Maybe
with the given attributes.
Synchronization::Object
- Inherited
.atomic_attribute?, .atomic_attributes, | |
.attr_atomic | Creates methods for reading and writing to a instance variable with volatile (Java) semantic as |
.attr_volatile | Creates methods for reading and writing (as |
.ensure_safe_initialization_when_final_fields_are_present | For testing purposes, quite slow. |
.new | Has to be called by children. |
.safe_initialization!, .define_initialize_atomic_fields |
Synchronization::AbstractObject
- Inherited
Instance Attribute Summary
-
#fulfilled?
readonly
Alias for #just?.
-
#just
(also: #value)
readonly
The value of a
Maybe
whenJust
. -
#just? ⇒ Boolean
(also: #fulfilled?)
readonly
Is this
Maybe
aJust
(successfully fulfilled with a value)? -
#nothing
(also: #reason)
readonly
The reason for the
Maybe
whenNothing
. -
#nothing? ⇒ Boolean
(also: #rejected?)
readonly
Is this
Maybe
a .nothing (rejected with an exception upon fulfillment)? -
#reason
readonly
Alias for #nothing.
-
#rejected?
readonly
Alias for #nothing?.
-
#value
readonly
Alias for #just.
Instance Method Summary
-
#<=>(other) ⇒ Integer
Comparison operator.
-
#or(other) ⇒ Object
Return either the value of self or the given default value.
Synchronization::Object
- Inherited
Synchronization::Volatile
- Included
Synchronization::AbstractObject
- Inherited
Constructor Details
.new(just, nothing) ⇒ Maybe
(private)
Create a new Maybe
with the given attributes.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 224
def initialize(just, nothing) @just = just @nothing = nothing end
Class Method Details
.from(*args) {|args| ... } ⇒ Maybe
Create a new Maybe
using the given block.
Runs the given block passing all function arguments to the block as block arguments. If the block runs to completion without raising an exception a new Just
is created with the value set to the return value of the block. If the block raises an exception a new Nothing
is created with the reason being set to the raised exception.
.just(value) ⇒ Maybe
Create a new Just
with the given value.
.nothing(error = '') ⇒ Maybe
Create a new Nothing
with the given (optional) reason.
Instance Attribute Details
#fulfilled? (readonly)
Alias for #just?.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 179
alias :fulfilled? :just?
#just (readonly) Also known as: #value
The value of a Maybe
when Just
. Will be NONE when Nothing
.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 114
attr_reader :just
#just? ⇒ Boolean
(readonly)
Also known as: #fulfilled?
Is this Maybe
a Just
(successfully fulfilled with a value)?
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 176
def just? ! nothing? end
#nothing (readonly) Also known as: #reason
The reason for the Maybe
when Nothing
. Will be NONE when Just
.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 117
attr_reader :nothing
#nothing? ⇒ Boolean
(readonly)
Also known as: #rejected?
Is this Maybe
a .nothing (rejected with an exception upon fulfillment)?
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 184
def nothing? @nothing != NONE end
#reason (readonly)
Alias for #nothing.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 191
alias :reason :nothing
#rejected? (readonly)
Alias for #nothing?.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 187
alias :rejected? :nothing?
#value (readonly)
Alias for #just.
# File 'lib/concurrent-ruby/concurrent/maybe.rb', line 189
alias :value :just
Instance Method Details
#<=>(other) ⇒ Integer
Comparison operator.
#or(other) ⇒ Object
Return either the value of self or the given default value.