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

Returns a new instance of 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) }.

Returns:

  • (Promise)

    the created promise.



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 }).

Parameters:

  • value (Object)

    the value to be returned by Promise#force.

Returns:

  • (Promise)

    the created promise.



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.

Returns:

  • (Promise)

    the created 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.

Returns:

  • (true, false)

    true if self is eager; otherwise, false.



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.

Returns:

  • (Object)

    the value of self.



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.

Returns:

  • (true, false)

    true if self is lazy; otherwise, false.



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

def lazy?
  content.type == :lazy
end