在Scala中,未来可能会失败,这可以异步发现:
f onComplete {
case Success(_) => println("Great!")
case Failure(t) => println("An error has occurred: " + t.getMessage)
}
你将如何“翻译”成Clojure?我的阅读让我相信Clojure未来/promise模型没有Scala的强大,你不能就这样抓住失败。那么该怎么办呢?
Scala的未来永远不需要被问到它的价值——当它好并准备好时,它会告诉你发生了什么(包括它是否失败——这是这个问题的关键)。这就是我所说的“异步”的意思。Scala的未来可以处于三种可能的状态之一——未完成、以失败告终、以成功告终。
Scala中一个典型的用例是一个返回Future[T]的远程调用,其中T是你真正想要得到的类型。如果远程JVM关闭,那么在超时之后,将会发生< code>case Failure(t)。
这是一个非常简单的模型。在这个问题中,我问的是一个简单的选择。顺便提一下,听说Clojure打算在某个时候采用Scala Futures模型是件好事。
未来宏只是包装一个Java未来,而deref阅读器宏只是针对未来调用. get()
的语法糖:
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中没有什么不同:您捕捉到一个< code>ExecutionException,请参阅java文档以了解更多信息:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()
因此,解决方案是从 deref
中捕获异常,如其他答案所示。
我想知道Clojure是否需要特定的结构来处理这种失败期货的情况。以下行为我提供了相同的功能:
(defn f-cond[f func-ok func-fail]
(future (try (func-ok @f) (catch Exception e (func-fail e)))))
然后:
@(f-cond (future (throw (Exception. "hi")))
identity #(println "Failed: " (.getCause %)))
结果
Failed: #<Exception java.lang.Exception: hi>
我记得Scala中的期货是单子,所以在< code>algo.monads和< code > fluo kiten 中搜索合适的东西。最后,我找到了雷纳多·博尔赫斯的《迫在眉睫》图书馆。我想这是你想要的。
有了这个名称空间声明
(ns imminent-proof.core
(:require [imminent.core :as i]
[clojure.core.match :refer [match]])
(:import [imminent.result Success Failure]))
这就是失败案例
(-> (i/future (/ 1 0))
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
这就是成功的例子
(-> (i/future (Thread/sleep 1000) 42)
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
这是超时的情况
(-> (i/future (Thread/sleep 1000) 42)
(i/await 500)
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
我正在寻找一种将任意长度的期货列表转换为期货列表的方法。我使用的是Playframework,所以最终,我真正想要的是一个<code>未来〔结果〕,但为了让事情更简单,让我们说<code>将来〔List[Int]]通常的方法是使用<code>Future.sequence(…) 例如,执行以下操作不起作用: 我希望能够将1和3从那里拉出来,而不是只得到异常。我尝试将来使用<code>。折叠,但这显
Scala中有没有不会失败的< code >未来这个概念? 我正在将可能失败,因此我同时处理和--到,并带有从失败或成功状态派生的可选错误消息。目前为止,一切都好。 现在的情况是,我想正式地(即在类型系统的帮助下)记住,这个未来将始终保持,并且我将来不需要处理失败案例。 有什么聪明的方法可以做到这一点吗?
在scala中失败的最干净的方法是什么? 说我有: 如果未来以成功,我想保留它,但是如果它失败了,我想将更改为其他。 我能想出的最好的是转换,但是这需要我为成功案例做一个不必要的函数: 有什么原因没有< code > mapFailure(partial function[Throwable,Throwable])?
我一直在使用助手来创建聚合期货,只有当它们的复合期货被标记为完成时才会成为“完成”,即: 我想对这一功能稍作改动,在以下情况下,总的未来市场是完整的: 所有期货均已成功完成或 在后一种情况下,总期货应立即完成(例外),而不必等待其他期货完成,即快速失败。 对比
我有一个未来[T],我想在成功和失败上映射结果。 比如说 如果我使用< code>map或< code>flatmap,它将只映射成功的未来。如果我使用< code>recover,它将只映射失败的期货。< code>onComplete执行回调,但不返回修改后的未来值。< code>Transform可以工作,但是需要两个函数而不是一个部分函数,所以有点难看。 我知道我可以做出一个新的,并用或/
我希望下面的代码在其中一个方法<code>callfuture1()</code>或<code>callfuture2()</code>抛出异常时返回自定义消息。我的理解是,如果任何一个未来失败,都将是失败的未来。 但是,当 引发异常时。 不执行。相反,我看到调用堆栈停止在 中的代码行,其中发生了异常并返回了标准内部错误。为什么会这样? ====更新==== 我从响应中看到,潜在的问题是异常被抛出