Class: Functional::FinalVar

Inherits:
Object
  • Object
show all
Defined in:
lib/functional/final_var.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.

A thread safe object that holds a single value and is "final" (meaning that the value can be set at most once after which it becomes immutable). The value can be set at instantiation which will result in the object becoming fully and immediately immutable. Attempting to set the value once it has been set is a logical error and will result in an exception being raised.

Examples:

Instanciation With No Value

f = Functional::FinalVar.new
  #=> #<Functional::FinalVar unset>
f.set?       #=> false
f.value      #=> nil
f.value = 42 #=> 42
f.inspect
  #=> "#<Functional::FinalVar value=42>"
f.set?       #=> true
f.value      #=> 42

Instanciation With an Initial Value

f = Functional::FinalVar.new(42)
  #=> #<Functional::FinalVar value=42>
f.set?       #=> true
f.value      #=> 42

See Also:

Since:

  • 1.1.0

Instance Method Summary collapse

Constructor Details

#initialize(value = NO_VALUE) ⇒ FinalVar

Create a new FinalVar with the given value or "unset" when no value is given.

Parameters:

  • value (Object) (defaults to: NO_VALUE)

    if given, the immutable value of the object

Since:

  • 1.1.0


55
56
57
58
# File 'lib/functional/final_var.rb', line 55

def initialize(value = NO_VALUE)
  @mutex = Mutex.new
  @value = value
end

Instance Method Details

#eql?(other) ⇒ Boolean Also known as: ==

Compares this object and other for equality. A FinalVar that is unset is never equal to anything else (it represents a complete absence of value). When set a FinalVar is equal to another FinalVar if they have the same value. A FinalVar is equal to another object if its value is equal to the other object using Ruby's normal equality rules.

Parameters:

  • other (Object)

    the object to compare equality to

Returns:

  • (Boolean)

    true if equal else false

Since:

  • 1.1.0


128
129
130
131
132
133
134
135
136
# File 'lib/functional/final_var.rb', line 128

def eql?(other)
  if (val = fetch(NO_VALUE)) == NO_VALUE
    false
  elsif other.is_a?(FinalVar)
    val == other.value
  else
    val == other
  end
end

#fetch(default) ⇒ Object

Get the value if set else return the given default value.

Parameters:

  • default (Object)

    the value to return if currently unset

Returns:

  • (Object)

    the current value when set else the given default

Since:

  • 1.1.0


114
115
116
117
118
# File 'lib/functional/final_var.rb', line 114

def fetch(default)
  @mutex.synchronize {
    has_been_set? ? @value : default
  }
end

#getObject Also known as: value

Get the current value or nil if unset.

Returns:

  • (Object)

    the current value or nil

Since:

  • 1.1.0


63
64
65
66
67
# File 'lib/functional/final_var.rb', line 63

def get
  @mutex.synchronize {
    has_been_set? ? @value : nil
  }
end

#get_or_set(value) ⇒ Object

Get the value if it has been set else set the value.

Parameters:

  • value (Object)

    the value to set

Returns:

  • (Object)

    the current value if already set else the new value

Since:

  • 1.1.0


100
101
102
103
104
105
106
107
108
# File 'lib/functional/final_var.rb', line 100

def get_or_set(value)
  @mutex.synchronize {
    if has_been_set?
      @value
    else
      @value = value
    end
  }
end

#set(value) ⇒ Object Also known as: value=

Set the value. Will raise an exception if already set.

Parameters:

  • value (Object)

    the value to set

Returns:

  • (Object)

    the new value

Raises:

Since:

  • 1.1.0


75
76
77
78
79
80
81
82
83
# File 'lib/functional/final_var.rb', line 75

def set(value)
  @mutex.synchronize {
    if has_been_set?
      raise FinalityError.new('value has already been set')
    else
      @value = value
    end
  }
end

#set?Boolean Also known as: value?

Has the value been set?

Returns:

  • (Boolean)

    true when the value has been set else false

Since:

  • 1.1.0


89
90
91
92
93
# File 'lib/functional/final_var.rb', line 89

def set?
  @mutex.synchronize {
    has_been_set?
  }
end