Question about future

4 views
Skip to first unread message

Hong Jiang

unread,
Nov 25, 2009, 12:04:38 AM11/25/09
to Clojure
Hi all,

I'm new to Clojure and playing with small programs. Today I wrote a
snippet to figure out how future works:

(defn testf []
(let [f (future #(do
(Thread/sleep 5000)
%)
5)
g 7]
(+ g @f)))

(println (testf))

I'm expecting the program to sleep 5 seconds and then print 12 and
immediately terminate. However, the program seems to print out 12
immediately, and it takes a long time (more like 50 seconds instead of
5) to terminate. Am I missing something?

Thanks.
--Hong

Sean Devlin

unread,
Nov 25, 2009, 9:21:57 AM11/25/09
to Clojure
I'm not quite sure what you're seeing. You might want to use the time
macro to help.

Here's what I was able to do:

user=> (time ((fn [] (let [f (future (#(do (Thread/sleep 5000) %) 5))
g 7] (+ g @f)))))
"Elapsed time: 4975.917889 msecs"
12

Sean

David Brown

unread,
Nov 25, 2009, 11:21:33 AM11/25/09
to clo...@googlegroups.com
On Tue, Nov 24, 2009 at 09:04:38PM -0800, Hong Jiang wrote:
>Hi all,
>
>I'm new to Clojure and playing with small programs. Today I wrote a
>snippet to figure out how future works:
>
>(defn testf []
> (let [f (future #(do
> (Thread/sleep 5000)
> %)
> 5)
> g 7]
> (+ g @f)))

You don't ever evaluate the function containing the sleep, you just
create it, and then immediately return 5.

Future contains an explicit do, so you can just do the steps in the
future:

[f (future
(Thread/sleep 5000)
5)
...

Or, if you want to get the function call in, you'll need to call it:

[f (future (#(do (Thread/sleep 5000) %) 5)) ...]

David

Meikel Brandmeyer

unread,
Nov 25, 2009, 9:22:48 AM11/25/09
to Clojure
Hi,
future takes a body not a function. So in the new thread, you create a
new anonymous function which is immediately thrown away and 5 is
returned. This explains why 12 is printed immediately. The shutdown
time might be connected to something like shutdown-agents. But I'm not
sure on this one. To test the hypothesis you can do something like
this:

(defn testf []
(let [f (future
#(do
(Thread/sleep 5000)
(+ % 6))
5)
g 7]
(+ g @f)))

This should print still 12 and not 18.

Sincerely
Meikel

Hong Jiang

unread,
Nov 25, 2009, 1:30:27 PM11/25/09
to Clojure
Thanks for your replies David and Sean. Yes, I made a mistake thinking
that future takes a function and its arguments, so the function was
never called in my program.

Kevin Downey

unread,
Nov 25, 2009, 4:15:39 PM11/25/09
to clo...@googlegroups.com
future also uses the same threadpool as agents, so once you call
future the threadpool spins up, and just sort of sits around for a
while before the jvm decides to exit, which is why the program would
sit around for 50 seconds
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en



--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

Hong Jiang

unread,
Nov 25, 2009, 6:32:56 PM11/25/09
to Clojure
Thanks. Yeah, after adding a call to shutdown-agents, the process no
longer hangs.

Robert Campbell

unread,
Nov 26, 2009, 2:05:19 AM11/26/09
to clo...@googlegroups.com
If you have this:

user> (def f (future (Thread/sleep 20000) :done))
#'user/f
user> @f ; this immediate deref blocks for 20 sec, finally returning :block
:done
user> @f ; returns immediately
:done

What is actually happening when you call the first @f? You are waiting
for the function to finish executing and return a value? Or are you
waiting for a return value to appear in the ref slot?

Is there any way to check if there is a value ready or if the function
has returned w/out blocking?

Christophe Grand

unread,
Nov 26, 2009, 2:11:46 AM11/26/09
to clo...@googlegroups.com
On Thu, Nov 26, 2009 at 8:05 AM, Robert Campbell <rrc...@gmail.com> wrote:
If you have this:

user> (def f (future (Thread/sleep 20000) :done))
#'user/f
user> @f  ; this immediate deref blocks for 20 sec, finally returning :block
:done
user> @f  ; returns immediately
:done

What is actually happening when you call the first @f? You are waiting
for the function to finish executing and return a value? Or are you
waiting for a return value to appear in the ref slot?

Is there any way to check if there is a value ready or if the function
has returned w/out blocking?

future-done?

user=> (def f (future (Thread/sleep 20000) :done))
#'user/f
user=> (future-done? f)
false
user=> @f
:done
user=> (future-done? f)
true

Christophe

John Harrop

unread,
Nov 26, 2009, 2:59:57 AM11/26/09
to clo...@googlegroups.com
On Thu, Nov 26, 2009 at 2:11 AM, Christophe Grand <chris...@cgrand.net> wrote:
On Thu, Nov 26, 2009 at 8:05 AM, Robert Campbell <rrc...@gmail.com> wrote:
If you have this:

user> (def f (future (Thread/sleep 20000) :done))
#'user/f
user> @f  ; this immediate deref blocks for 20 sec, finally returning :block
:done
user> @f  ; returns immediately
:done

What is actually happening when you call the first @f? You are waiting
for the function to finish executing and return a value? Or are you
waiting for a return value to appear in the ref slot?

Is there any way to check if there is a value ready or if the function
has returned w/out blocking?

future-done?

Why isn't this on the api page? 

lpetit

unread,
Dec 9, 2009, 3:47:14 AM12/9/09
to Clojure
Please also note the existence of (future-call), which takes a no-arg
fn instead of a body,

HTH,

--
Laurent
Reply all
Reply to author
Forward
0 new messages