Class: Functional::Option

Inherits:
Object
  • Object
show all
Includes:
AbstractStruct
Defined in:
lib/functional/option.rb

Overview

Note:

This is a write-once, read-many, thread safe object that can be used in concurrent systems. Thread safety guarantees cannot be made about objects contained within this object, however. Ruby variables are mutable references to mutable objects. This cannot be changed. The best practice it to only encapsulate immutable, frozen, or thread safe objects. Ultimately, thread safety is the responsibility of the programmer.

An optional value that may be none (no value) or some (a value). This type is a replacement for the use of nil with better type checks. It is an immutable data structure that extends AbstractStruct.

See Also:

Since:

  • 1.0.0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#reasonObject (readonly)

The reason for the absence of a value when none, defaults to nil

Since:

  • 1.0.0



36
37
38
# File 'lib/functional/option.rb', line 36

def reason
  @reason
end

#valuesArray (readonly) Originally defined in module AbstractStruct

Returns the values of all record fields in order, frozen

Returns:

  • (Array)

    the values of all record fields in order, frozen

Since:

  • 1.0.0

Class Method Details

.iff(value, condition = NO_OPTION) { ... } ⇒ Option

If the condition satisfies, return the given A in some, otherwise, none.

Parameters:

  • value (Object)

    The some value to use if the condition satisfies.

  • condition (Boolean) (defaults to: NO_OPTION)

    The condition to test (when no block given).

Yields:

  • The condition to test (when no condition given).

Returns:

  • (Option)

    A constructed option based on the given condition.

Raises:

  • (ArgumentError)

    When both a condition and a block are given.

Since:

  • 1.0.0



182
183
184
185
186
# File 'lib/functional/option.rb', line 182

def self.iff(value, condition = NO_OPTION)
  raise ArgumentError.new('requires either a condition or a block, not both') if condition != NO_OPTION && block_given?
  condition = block_given? ? yield : !! condition
  condition ? some(value) : none
end

.none(reason = nil) ⇒ Option

Construct an Option with no value.

Returns:

Since:

  • 1.0.0



43
44
45
# File 'lib/functional/option.rb', line 43

def none(reason = nil)
  new(nil, true, reason).freeze
end

.some(value) ⇒ Option

Construct an Option with the given value.

Parameters:

  • value (Object)

    the value of the option

Returns:

Since:

  • 1.0.0



51
52
53
# File 'lib/functional/option.rb', line 51

def some(value)
  new(value, false).freeze
end

Instance Method Details

#and(other = NO_OPTION) {|value| ... } ⇒ Boolean

Perform a logical and operation against this option and the provided option or block. Returns true if this option is some and:

  • other is an Option with some value
  • other is a truthy value (not nil or false)
  • the result of the block is a truthy value

If a block is given the value of the current option is passed to the block and the result of block processing will be evaluated for its truthiness. An exception will be raised if an other value and a block are both provided.

Parameters:

  • other (Object) (defaults to: NO_OPTION)

    the value to be evaluated against this option

Yield Parameters:

  • value (Object)

    the value of this option when some

Returns:

  • (Boolean)

    true when the union succeeds else false

Raises:

  • (ArgumentError)

    when given both other and a block

Since:

  • 1.0.0



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/functional/option.rb', line 108

def and(other = NO_OPTION)
  raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
  return false if none?

  if block_given?
    !! yield(some)
  elsif Protocol::Satisfy? other, :Option
    other.some?
  else
    !! other
  end
end

#each {|value| ... } ⇒ Enumerable Originally defined in module AbstractStruct

Yields the value of each record field in order. If no block is given an enumerator is returned.

Yield Parameters:

  • value (Object)

    the value of the given field

Returns:

  • (Enumerable)

    when no block is given

Since:

  • 1.0.0

#each_pair {|field, value| ... } ⇒ Enumerable Originally defined in module AbstractStruct

Yields the name and value of each record field in order. If no block is given an enumerator is returned.

Yield Parameters:

  • field (Symbol)

    the record field for the current iteration

  • value (Object)

    the value of the current field

Returns:

  • (Enumerable)

    when no block is given

Since:

  • 1.0.0

#else(other = NO_OPTION) ⇒ Object

Returns the value of this option when some else returns the value of the other option or block. When the other is also an option its some value is returned. When the other is any other value it is simply passed through. When a block is provided the block is processed and the return value of the block is returned. An exception will be raised if an other value and a block are both provided.

Parameters:

  • other (Object) (defaults to: NO_OPTION)

    the value to be evaluated when this is none

Returns:

  • (Object)

    this value when some else the value of other

Raises:

  • (ArgumentError)

    when given both other and a block

Since:

  • 1.0.0



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/functional/option.rb', line 160

def else(other = NO_OPTION)
  raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
  return some if some?

  if block_given?
    yield
  elsif Protocol::Satisfy? other, :Option
    other.some
  else
    other
  end
end

#eql?(other) ⇒ Boolean Also known as: == Originally defined in module AbstractStruct

Equality--Returns true if other has the same record subclass and has equal field values (according to Object#==).

Parameters:

  • other (Object)

    the other record to compare for equality

Returns:

  • (Boolean)

    true when equal else false

Since:

  • 1.0.0

#fieldsArray Originally defined in module AbstractStruct

A frozen array of all record fields.

Returns:

  • (Array)

    all record fields in order, frozen

Since:

  • 1.0.0

#inspectString Also known as: to_s

Describe the contents of this struct in a string. Will include the name of the record class, all fields, and all values.

Returns:

  • (String)

    the class and contents of this record

Since:

  • 1.0.0



189
190
191
# File 'lib/functional/option.rb', line 189

def inspect
  super.gsub(/ :some/, " (#{some? ? 'some' : 'none'}) :some")
end

#lengthFixnum Also known as: size

Returns the length of this optional value; 1 if there is a value, 0 otherwise.

Returns:

  • (Fixnum)

    The length of this optional value; 1 if there is a value, 0 otherwise.

Since:

  • 1.0.0



87
88
89
# File 'lib/functional/option.rb', line 87

def length
  none? ? 0 : 1
end

#none?Boolean Also known as: reason?, rejected?

Is the option absent a value?

Returns:

  • (Boolean)

    true if none else false

Since:

  • 1.0.0



68
69
70
# File 'lib/functional/option.rb', line 68

def none?
  @none
end

#or(other = NO_OPTION) ⇒ Boolean

Perform a logical or operation against this option and the provided option or block. Returns true if this option is some. If this option is none it returns true if:

  • other is an Option with some value
  • other is a truthy value (not nil or false)
  • the result of the block is a truthy value

If a block is given the value of the result of block processing will be evaluated for its truthiness. An exception will be raised if an other value and a block are both provided.

Parameters:

  • other (Object) (defaults to: NO_OPTION)

    the value to be evaluated against this option

Returns:

  • (Boolean)

    true when the intersection succeeds else false

Raises:

  • (ArgumentError)

    when given both other and a block

Since:

  • 1.0.0



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/functional/option.rb', line 136

def or(other = NO_OPTION)
  raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
  return true if some?

  if block_given?
    !! yield
  elsif Protocol::Satisfy? other, :Option
    other.some?
  else
    !! other
  end
end

#someObject Also known as: value

The value of this option.

Returns:

  • (Object)

    the value when some else nil

Since:

  • 1.0.0



77
78
79
# File 'lib/functional/option.rb', line 77

def some
  to_h[:some]
end

#some?Boolean Also known as: value?, fulfilled?

Does the option have a value?

Returns:

  • (Boolean)

    true if some else false

Since:

  • 1.0.0



59
60
61
# File 'lib/functional/option.rb', line 59

def some?
  ! none?
end

#to_hHash Originally defined in module AbstractStruct

Returns a Hash containing the names and values for the record’s fields.

Returns:

  • (Hash)

    collection of all fields and their associated values

Since:

  • 1.0.0