The following works. The result is "hello world"
(def ^Callable f (fn [] "hello world"))
(let [e (java.util.concurrent.Executors/newSingleThreadExecutor)]
(try
(.get (.submit e f))
(finally (.shutdown e))))
But the following doesn't. The result of get
is nil
(def e (java.util.concurrent.Executors/newSingleThreadExecutor))
(.get (.submit e f))
Why? I checked that f
is getting called by replacing it with something that has a side effect. The only difference I can see is that e
is bound using let
in one and def
in the other.
Another question. If I don't have the ^Callable
typehint for f
the first example quietly returns nil
. Shouldn't it throw an exception "more than one matching method found" for the submit call since f
is both Runnable
and Callable
? If I define f
using let
like the following then the exception is thrown
(let [e (java.util.concurrent.Executors/newSingleThreadExecutor)]
(let [f (fn [] "hello world2")]
(try
(.get (.submit e f))
(finally (.shutdown e)))))
Thanks
The problem was the type of e
could not be inferred in
(def e (java.util.concurrent.Executors/newSingleThreadExecutor))
when I change this to
(def ^java.util.concurrent.ExecutorService e (java.util.concurrent.Executors/newSingleThreadExecutor))
then (.get (.submit e f))
gives proper answer "hello world"
. Somehow clojure is inferring the correct type when e
is defined using a let
and thus does not require a similar type hint.
setting *warn-on-reflection*
to true
helped to debug this.