Future failure in Clojure
在Scala中,未来可能会失败,并且可以异步找到它:
1 2 3 4 |
您如何将其"翻译"为Clojure?我的阅读使我相信,Clojure的未来/Promise模型不如Scala强大,并且您不能仅仅抓住这样的失败。那么该怎么做呢?
Scala的未来永远都不需要问它的价值-当它做好并准备就绪时,它将告诉您发生了什么(包括它是否失败了-这是这个问题的关键)。这就是我"异步"的意思。 Scala的未来可能处于三种可能的状态之一-未完成,失败完成,成功完成。
Scala中一个用例的典型示例是一个返回Future [T]的远程调用,其中T是您真正想要返回的类型。如果远程JVM关闭,则在超时后将发生
这是一个非常简单的模型。在这个问题上,我要求一个简单的选择。作为附带评论,很高兴听到Clojure打算在某个时候采用Scala期货模型。
我记得Scala的期货是monads,所以在
在此命名空间声明正确的地方
1 2 3 4 |
这是失败案例
1 2 3 4 | (-> (i/future (/ 1 0)) (i/on-complete #(match [%] [{Success v}] (prn"success:" v) [{Failure e}] (prn"failure:" e)))) |
成功案例
1 2 3 4 | (-> (i/future (Thread/sleep 1000) 42) (i/on-complete #(match [%] [{Success v}] (prn"success:" v) [{Failure e}] (prn"failure:" e)))) |
这是超时情况
1 2 3 4 5 | (-> (i/future (Thread/sleep 1000) 42) (i/await 500) (i/on-complete #(match [%] [{Success v}] (prn"success:" v) [{Failure e}] (prn"failure:" e)))) |
future宏只是packageJava Future,而deref reader宏只是用于针对future调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | user=> (source future) (defmacro future "Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block, unless the variant of deref with timeout is used. See also - realized?." {:added"1.1"} [& body] `(future-call (^{:once true} fn* [] ~@body))) nil user=> (source future-call) (defn future-call "Takes a function of no args and yields a future object that will invoke the function in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block, unless the variant of deref with timeout is used. See also - realized?." {:added"1.1" :static true} [f] (let [f (binding-conveyor-fn f) fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] (reify clojure.lang.IDeref (deref [] (deref-future fut)) clojure.lang.IBlockingDeref (deref [ timeout-ms timeout-val] (deref-future fut timeout-ms timeout-val)) clojure.lang.IPending (isRealized [] (.isDone fut)) java.util.concurrent.Future (get [] (.get fut)) (get [_ timeout unit] (.get fut timeout unit)) (isCancelled [] (.isCancelled fut)) (isDone [] (.isDone fut)) (cancel [_ interrupt?] (.cancel fut interrupt?))))) nil user=> |
因此测试失败与在Java中进行测试没有什么不同:您捕获到
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()
因此解决方案是从
我想知道Clojure是否需要特定的构造来处理期货失败的情况。以下行为我提供了相同的功能:
然后:
1 2 |
产生
1 | Failed: #<Exception java.lang.Exception: hi> |