Class: Promise

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

Overview

A delayed-execution promise. Promises are only executed once.

Examples:

x = promise { factorial 20 }
y = promise { fibonacci 10**6 }
a = x + 1     # => factorial 20 + 1 after factorial calculates
result = promise { a += y }
abort ""      # whew, we never needed to calculate y

y = 5
x = promise { y = y + 5 }
x + 5     # => 15
x + 5     # => 15

Constant Summary

NOT_SET =
::Object.new.freeze

Instance Method Summary (collapse)

Constructor Details

- (Promise) initialize { ... }

Creates a new promise.

Examples:

Lazily evaluate a database call

result = promise { @db.query("SELECT * FROM TABLE") }

Yields:

  • [] The block to evaluate lazily.

See Also:



30
31
32
33
34
35
36
37
38
# File 'lib/promise.rb', line 30

def initialize(&block)
  if block.arity > 0
    raise ArgumentError, "Cannot store a promise that requires an argument"
  end
  @block  = block
  @mutex  = ::Mutex.new
  @result = NOT_SET
  @error  = NOT_SET
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(method, *args, &block) (private)



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

def method_missing(method, *args, &block)
  __force__.__send__(method, *args, &block)
end

Instance Method Details

- (Object) __force__ Also known as: force

Force the evaluation of this promise immediately

Returns:

  • (Object)


44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/promise.rb', line 44

def __force__
  @mutex.synchronize do
    if @result.equal?(NOT_SET) && @error.equal?(NOT_SET)
      begin
        @result = @block.call
      rescue ::Exception => e
        @error = e
      end
    end
  end if @result.equal?(NOT_SET) && @error.equal?(NOT_SET)
  # BasicObject won't send raise to Kernel
  @error.equal?(NOT_SET) ? @result : ::Kernel.raise(@error)
end

- (Boolean) respond_to?(method)

Does this promise support the given method?

Parameters:

  • (Symbol)

Returns:

  • (Boolean)


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

def respond_to?(method)
  :force.equal?(method) || :__force__.equal?(method) || __force__.respond_to?(method)
end