Class: Immutable::Promise

Inherits:
Object
  • Object
show all
Defined in:
lib/immutable/promise.rb

Overview

Immutable::Promise represents a promise to evaluate an expression later.

Examples:

Delayed computation

promise = Promise.delay { puts "hello"; 1 + 2 }
x = promise.force #=> hello
p x               #=> 3
y = promise.force #=> (no output; the value is memoized)
p y               #=> 3

Infinite streams

def from(n)
  Promise.delay {
    Cons[n, from(n + 1)]
  }
end

def stream_ref(s, n)
  xs = s.force
  if xs.empty?
    nil
  else
    n == 0 ? xs.head : stream_ref(xs.tail, n - 1)
  end
end

nats = from(0)
p stream_ref(nats, 0) #=> 0
p stream_ref(nats, 3) #=> 3

Direct Known Subclasses

Stream

Defined Under Namespace

Classes: Content

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, value) ⇒ Promise



34
35
36
# File 'lib/immutable/promise.rb', line 34

def initialize(type, value)
  @content = Content.new(type, value)
end

Class Method Details

.delayPromise

Takes a block, and returns a promise which at some point in the future may be asked (by Promise#force) to evaluate the block and deliver the resulting value.

Promise.delay { expression } is equivalent to Promise.lazy { Promise.eager(expression) }.



83
84
85
86
87
# File 'lib/immutable/promise.rb', line 83

def self.delay
  lazy {
    eager(yield)
  }
end

.eager(value) ⇒ Promise

Takes an argument, and returns a promise which deliver the value of the argument.

Promise.eager(expresion) is equivalent to (value = Promise.eager; Promise.delay { value }).



57
58
59
# File 'lib/immutable/promise.rb', line 57

def self.eager(value)
  new(:eager, value)
end

.lazy(&block) ⇒ Promise

Takes a block which evaluates to a promise, and returns a promise which at some point in the future may be asked (by Promise#force) to evaluate the block and deliver the value of the resulting promise.



45
46
47
# File 'lib/immutable/promise.rb', line 45

def self.lazy(&block)
  new(:lazy, block)
end

Instance Method Details

#eager?true, false

Returns whether self is eager.



71
72
73
# File 'lib/immutable/promise.rb', line 71

def eager?
  content.type == :eager
end

#forceObject

Returns the value of self. If a value of self has already been computated, the value is returned. Otherwise, the promise is first evaluated, and the resulting value is returned.



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/immutable/promise.rb', line 95

def force
  case content.type
  when :eager
    content.value
  when :lazy
    promise = content.value.call
    if content.type != :eager
      content.type = promise.content.type
      content.value = promise.content.value
      promise.content = content
    end
    force
  else
    raise ScriptError, "should not reach here"
  end
end

#lazy?true, false

Returns whether self is lazy.



64
65
66
# File 'lib/immutable/promise.rb', line 64

def lazy?
  content.type == :lazy
end