Sha256: fb8e7f44af53e95d91b56ad8e0ea3fea5a87406da0fea7ee27aababe158fe84f

Contents?: true

Size: 1.27 KB

Versions: 1

Compression:

Stored size: 1.27 KB

Contents

##
# A delayed-execution promise.  Promises are only executed once.
# @example
#     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
# @example
#     y = 5
#     x = promise { y = y + 5 }
#     x + 5     # => 15
#     x + 5     # => 15
class Promise < defined?(BasicObject) ? BasicObject : Object

  instance_methods.each { |m| undef_method m unless m =~ /__|object_id/ } unless defined?(BasicObject)

  # Returns a new promise
  # @param [Proc] block
  # @return [Promise]
  def initialize(block)
    if block.arity > 0
      raise ArgumentError, "Cannot store a promise that requires an argument"
    end
    @block = block
    @mutex = ::Mutex.new
  end

  # Force the evaluation of this promise immediately
  # @return [Any]
  def force
    @mutex.synchronize do 
      unless @result
        @result = @block.call
      end
    end
    @result
  end

  def method_missing(method, *args, &block)
    force unless @result
    @result.send(method, *args, &block)
  end
end

module Kernel
  
  # Create a new promise
  # @example
  #     x = promise { 3 + 3 }
  def promise(&block)
    Promise.new(block)
  end

end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
promise-0.1.1 lib/promise.rb