Futures and promises are the simplest async building blocks you’ll see in Clojure codebases. Both are derefable, so @x blocks until a value is available (or returns immediately if realized).
Futures: Run a Computation Asynchronously
1(def f (future
2 (Thread/sleep 100)
3 42))
4
5(realized? f) ; => false (usually)
6@f ; blocks, then => 42
If you need it, Clojure also provides:
future-cancel, future-cancelled?, future-done?
Promises: A One-Time Value Delivered Later
1(def p (promise))
2
3(future (deliver p 42))
4
5@p ; blocks until delivered => 42
You can avoid blocking forever with a timeout:
1(deref p 1000 :timeout) ; => 42 (or :timeout if not delivered in time)
Knowledge Check: Futures and Promises
### What does dereferencing a future (like `@f`) do?
- [x] Blocks until the computation finishes, then returns its result (or throws its exception).
- [ ] Cancels the future.
- [ ] Forces the future to run on the current thread.
- [ ] Returns `nil` until the future completes.
> **Explanation:** Futures are derefable. Deref blocks until a result is ready.
### What does `deliver` do for a promise?
- [x] Completes the promise with a value (one-time), unblocking deref.
- [ ] Starts a new thread pool.
- [ ] Retries a promise computation under contention.
- [ ] Converts a promise into a future.
> **Explanation:** A promise is a placeholder. `deliver` sets its value once.
### How can you avoid blocking forever on a promise?
- [x] Use `(deref p timeout-ms timeout-val)` (or check `realized?`).
- [ ] Use `swap!` on the promise.
- [ ] Use `dosync`.
- [ ] Use `conj`.
> **Explanation:** `deref` supports a timeout and default value. `realized?` can tell you whether a derefable has a value already.