In Scala a future can fail and this can be found out asynchronously:
f onComplete {
case Success(_) => println("Great!")
case Failure(t) => println("An error has occurred: " + t.getMessage)
}
How would you 'translate' this into Clojure? My reading leads me to believe that the Clojure future/promise model is not as powerful as Scala's, and you can't just catch the failure like this. So what to do instead?
A Scala future never needs to be asked for it's value - when it is good and ready it will tell you what happened (including whether it failed - that's the crux of this question). This is what I meant by 'asynchronously'. A Scala future can be in one of three possible states - uncompleted, completed with failure, completed with success.
A typical example of a use case in Scala is a remote call that returns a Future[T], where T is the type of what you really want to get back. If the remote JVM is down then after a timeout the case Failure(t) will happen.
This is quite a straightforward model to work with. In the question I was asking for a simple alternative. As a side-comment it would be good to hear that Clojure intends to adopt the Scala Futures model at some point.
I remember futures in Scala are monads so searched algo.monads and fluokitten for something suitable. Finally I found Lenardo Borges' imminent library. I think it's what you want.
With this namespace declaration in place
(ns imminent-proof.core
(:require [imminent.core :as i]
[clojure.core.match :refer [match]])
(:import [imminent.result Success Failure]))
This is the failure case
(-> (i/future (/ 1 0))
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
This the success case
(-> (i/future (Thread/sleep 1000) 42)
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
And this the timeout case
(-> (i/future (Thread/sleep 1000) 42)
(i/await 500)
(i/on-complete #(match [%]
[{Success v}] (prn "success: " v)
[{Failure e}] (prn "failure: " e))))
I wonder if Clojure need specific construct to handle this situation with failed futures. The following line gives me the same functionality:
(defn f-cond[f func-ok func-fail]
(future (try (func-ok #f) (catch Exception e (func-fail e)))))
Then:
#(f-cond (future (throw (Exception. "hi")))
identity #(println "Failed: " (.getCause %)))
results in
Failed: #<Exception java.lang.Exception: hi>
the future macro is just wrapping a Java Future, and the deref reader macro is just syntax sugar for calling .get() against the future:
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=>
So testing for failure is no different than in java: you catch an ExecutionException, see java doc for Future:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()
So the solution is to catch the exception from the deref, as shown in other answers.
Related
I'm sporadically getting util.NoSuchElementException: Future.filter predicate is not satisfied exceptions.
My understanding from other questions is that this appears with if guards in for comprehensions. I extensively use for comprehensions but I can't find any conditions. I do however make some assignments.
for {
foo <- Future{0}
bar = foo + 1
} yield bar
However, my understanding is that this should be fine.
I'm struggling to find the source of the runtime exception. Are there other cases where Future.filter would be called, besides if guards? Any other ideas of what I should be looking for?
Edit:
Could this be caused by pattern matching, like
for {
foo <- Future{0 -> 1}
(bar, _) <- foo
} yield bar + 1
Edit2:
I'm guessing the above is fine but this might cause a RTE?
for {
(bar, _) <- Future{0 -> 1}
} yield bar + 1
.filter and .withFilter (lazy version preferred by for-comprehension) remove from your F[_] values that don't fulfill the predicate:
with List it removed values from the List and returns a List with those values removed
with Option it turns Some to None if predicate is not fulfilled
with Try - it's similar to Option but Success is treated like Some, and Failure like None - however Failure cannot be empty, and that's why it puts Exception there
Future is asynchronous Try.
For that reason .withFilter(condition) is basically lazy version of
.flatMap { value =>
if (condition(value)) => Future.successful(value)
else Future.failed(new util.NoSuchElementException("Future.filter predicate is not satisfied"))
}
You will get that for every case that call .withFilter on Future underneath. With for comprehension that would be:
direct call of .withFilter
usage of if clause
usage of pattern matching
for {
f <- future.withFilter(cond1) // this might raise exception
g <- makeFuture(f) if cond2 // this might raise
(head, tail) <- makeFutureList(g) // this might raise
} yield
To avoid it (in Future or other IO monads)
don't call withFilter manually
instead of if use if-else:
for {
value <- future
success <- if (cond(value)) Future.successful(value)
else Future.failed(yourOwnError) // handle however you like
} yield success
You can also use better monadic for to avoid using .withFilter on pattern matching which cannot fail (though if they can fail you would still get exception, so it's not a solution, but still nice a way of getting rid of unwanted .withFilter).
For instance, Folly supports the non-blocking combinator collectN which can be found here https://github.com/facebook/folly/blob/master/folly/futures/helpers.h
It does not provide a non-blocking combinator collectNWithoutException which would only collect successful futures similiar to collectAny but for more than one resulting future.
Scala seems to provide only firstCompletedOf which would be collectN with n == 1.
How can I easily implement these non-blocking combinators if Scala does not support them?
I would like to use the existing combinators for the implementation.
This is not practical for big number of futures, but a demonstration of available combinators
def firstNCompleted[T](n: Int, futures: List[Future[T]])(implicit executor: ExecutionContext): Future[List[T]] =
Future.firstCompletedOf(futures.combinations(n).map(Future.sequence(_)))
creates all combinations of n futures Iterator[List[Future[T]]]
sequences each combination into Future of resulting list Iterator[Future[List[T]]]
returns first completed Future[List[T]]
Here is collectN:
def collectN[T](n: Int, futures: List[Future[T]]): Future[List[T]] = {
val promise = Promise[List[T]]
var result:List[T] = Nil
futures.foreach {
_.onComplete {
case _ if result.length >= n =>
case Success(t) => synchronized {
result = t :: result
if(result.length == n) promise.success(result.reversed.take(n))
}
case Failure(x) => promise.failure(x)
}
}
promise.future
}
Note, that it returns a Future that will never complete if the number of input futures is less than n (and they all succeed).
You can modify it trivially to keep waiting until N successes rather than aborting after first failure, but that would also end up waiting forever if less than N of futures end up succeeding. To avoid that, you could count the number of the ones that have completed, and bail out after it reaches the size of the original list.
I have the following snippet in Scala using Scalaz and Task/EitherT:
def myMethod(request: MyRequest) : EitherT[Task, Failure, Success] =
EitherT[Task, Failure, Success](
for {
aamOpt <- async.findUser(request)
aamEith <- Task.now(aamOpt.\/>(NoUserFound()))
result <- aamEith.fold(err => Task.now(-\/(err)), aam => process(aam)).run)
} yield result)
Where async.findUser returns a Task[Option[MyUser]] and process(aam) returns EitherT[Task, Failure, Success]. These return types are needed as these methods interact (down the line) with external services.
Is there any way to simplify the last line of the for comprehension into something nicer? I mean this one:
result <- aamEith.fold(err => Task.now(-\/(err)), aam => process(aam)).run)
I would probably immediately lift the result from async.findUser into the relevant EitherT monad and then just flatMap:
def myMethod(request: MyRequest): EitherT[Task, Failure, Success] =
EitherT.eitherT[Task, Failure, MyUser](
async.findUser(request).map(_.\/>(NoUserFound()))
).flatMap(process)
This is untested but something like it should more or less work.
I am struggling to understand how this code 'strips out' the Future.
getFutureResult() returns a Future[String]. So how come the return from the yield is only a String?
def getFutureResult:Future[String] = { ... }
def getMyResult:String = {
for {
myFutureResult <- getFutureResult()
} yield {
myFutureResult
}
}
It is translated according to Scala for-comprehension translation rules:
for (x <- <expr>) yield f(x)
becomes:
<expr>.map(x => f(x))
This is a desugaring done by the compiler irregardless if <expr> has the type of a collection, a future or something else.
Future in Scala has a method map, so it uses the myFutureResult String from above to construct another Future[String].
You never know if the resulting future getMyResult is completed -- you should install an onComplete callback that will be called by the resulting future once it completes:
getMyResult onComplete {
case Success(x) => println("Yes! " + x)
case Failure(t) => println("An error: " + t)
}
The code for the onComplete method is executed asynchronously -- it might happen on a different thread, much later or simultaneously.
If you really need to know if the Future has completed, use the:
Await(getMyResult, 0 nanos)
pattern to block the calling thread until the getMyResult future is completed. In general, you should avoid this and compose your Future code using for-comprehensions and callback.
In Clojure, the branch of an if expression that doesn't match the condition is not evaluated, so no exception is thrown in evaluating the below expression:
=> (if nil (/ 1 0))
nil
However, macros will still be expanded before evaluating the if, so you can still get exceptions like so:
=> (if nil (proxy [nil] []))
CompilerException java.lang.NullPointerException, compiling:(NO_SOURCE_PATH:1)
I'm writing a macro for which the name of an interface will sometimes be provided as an arg, in which case the macro will generate the code for a call to proxy. Other times, the interface arg will be nil, and then the macro expands to something like (if nil (proxy [nil] []), so I get the above exception. An SSCE would be:
=> (defmacro make-listener [listener-name & methods]
`(if ~listener-name
(proxy [~listener-name] []
~#(map (fn [m] `(~m [e#])) methods))))
#'user/make-listener
=> (make-listener java.awt.event.ActionListener actionPerformed)
#<Object$ActionListener$46793e3a user.proxy$java.lang.Object$ActionListener$46793e3a#ed5b2>
=> (make-listener nil)
CompilerException java.lang.NullPointerException, compiling:(NO_SOURCE_PATH:1)
How can I write the macro in a way that doesn't throw an exception when no interface arg is provided?
If listener-name is nil then the macro should do nothing i.e you need to check for listener-name at macro expansion (not in the code the macro emit).
(defmacro make-listener [listener-name & methods]
(if listener-name
`(proxy [~listener-name] []
~#(map (fn [m] `(~m [e#])) methods))))