lib/promise.rb in promise-0.2.0 vs lib/promise.rb in promise-0.2.1

- old
+ new

@@ -1,85 +1,90 @@ ## # 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 +# 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 +# y = 5 +# x = promise { y = y + 5 } +# x + 5 # => 15 +# x + 5 # => 15 +# class Promise < defined?(BasicObject) ? BasicObject : ::Object + NOT_SET = ::Object.new.freeze instance_methods.each { |m| undef_method m unless m.to_s =~ /__/ } - NOT_SET = ::Object.new.freeze - ## - # Create a new promise + # Creates a new promise. # # @example Lazily evaluate a database call - # result = promise { @db.query("SELECT * FROM TABLE") } - # @param [Proc] block - # @return [Promise] - # @see Kernel#promise - def initialize(block) + # result = promise { @db.query("SELECT * FROM TABLE") } + # + # @yield [] The block to evaluate lazily. + # @see Kernel#promise + def initialize(&block) if block.arity > 0 raise ArgumentError, "Cannot store a promise that requires an argument" end - @block = block - @mutex = ::Mutex.new + @block = block + @mutex = ::Mutex.new @result = NOT_SET @error = NOT_SET end ## # Force the evaluation of this promise immediately # - # @return [Any] + # @return [Object] def __force__ @mutex.synchronize do - if @result == NOT_SET && @error == NOT_SET + if @result.equal?(NOT_SET) && @error.equal?(NOT_SET) begin @result = @block.call rescue ::Exception => e @error = e end end - end if @result == NOT_SET && @error == NOT_SET + 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) + @error.equal?(NOT_SET) ? @result : ::Kernel.raise(@error) end alias_method :force, :__force__ ## # Does this promise support the given method? # # @param [Symbol] - # @return [true, false] + # @return [Boolean] def respond_to?(method) - (method == :force) || (method == :__force__) || (__force__.respond_to?(method)) + :force.equal?(method) || :__force__.equal?(method) || __force__.respond_to?(method) end + private + def method_missing(method, *args, &block) - __force__ - @result.send(method, *args, &block) + __force__.__send__(method, *args, &block) end end module Kernel - - # Create a new promise + ## + # Creates a new promise. # # @example Lazily evaluate an arithmetic operation - # x = promise { 3 + 3 } - # @return [Promise] - # @yield [] A block to be lazily evaluated - # @yieldreturn [Any] The return value of the block will be the lazily evaluated value of the promise. + # x = promise { 3 + 3 } + # + # @yield [] + # A block to be lazily evaluated. + # @yieldreturn [Object] + # The return value of the block will be the lazily evaluated value of the promise. + # @return [Promise] def promise(&block) - Promise.new(block) + Promise.new(&block) end - end