class Functional::FinalVar
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.
@example 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
@example Instanciation With an Initial Value
f = Functional::FinalVar.new(42) #=> #<Functional::FinalVar value=42> f.set? #=> true f.value #=> 42
@see Functional::FinalStruct
@see en.wikipedia.org/wiki/Final_(Java) Java ‘final` keyword
@!macro [new] thread_safe_final_object
@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.
Constants
- NO_VALUE
@!visibility private
Public Class Methods
Create a new ‘FinalVar` with the given value or “unset” when no value is given.
@param [Object] value if given, the immutable value of the object
# File lib/functional/final_var.rb, line 53 def initialize(value = NO_VALUE) super synchronize{ @value = value } end
Public Instance Methods
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.
@param [Object] other the object to compare equality to @return [Boolean] true if equal else false
# File lib/functional/final_var.rb, line 120 def eql?(other) if (val = fetch(NO_VALUE)) == NO_VALUE false elsif other.is_a?(FinalVar) val == other.value else val == other end end
Get the value if set else return the given default value.
@param [Object] default the value to return if currently unset @return [Object] the current value when set else the given default
# File lib/functional/final_var.rb, line 108 def fetch(default) synchronize { has_been_set? ? @value : default } end
Get the current value or nil if unset.
@return [Object] the current value or nil
# File lib/functional/final_var.rb, line 61 def get synchronize { has_been_set? ? @value : nil } end
Get the value if it has been set else set the value.
@param [Object] value the value to set @return [Object] the current value if already set else the new value
# File lib/functional/final_var.rb, line 94 def get_or_set(value) synchronize do if has_been_set? @value else @value = value end end end
Describe the contents of this object in a string.
@return [String] the string representation of this object
@!visibility private
# File lib/functional/final_var.rb, line 136 def inspect if (val = fetch(NO_VALUE)) == NO_VALUE val = 'unset' else val = "value=#{val.is_a?(String) ? ('"' + val + '"') : val }" end "#<#{self.class} #{val}>" end
Set the value. Will raise an exception if already set.
@param [Object] value the value to set @return [Object] the new value @raise [Functional::FinalityError] if the value has already been set
# File lib/functional/final_var.rb, line 71 def set(value) synchronize do if has_been_set? raise FinalityError.new('value has already been set') else @value = value end end end
Has the value been set?
@return [Boolean] true when the value has been set else false
# File lib/functional/final_var.rb, line 85 def set? synchronize { has_been_set? } end
Describe the contents of this object in a string.
@return [String] the string representation of this object
@!visibility private
# File lib/functional/final_var.rb, line 150 def to_s value.to_s end
Private Instance Methods
Checks the set status without locking the mutex. @return [Boolean] true when set else false
# File lib/functional/final_var.rb, line 158 def has_been_set? @value != NO_VALUE end