1    Introduction

1.1    Overview

std.lib.future is part of the standard foundation library set. This page collects the public API reference for the namespace.

2    Walkthrough

2.1    Creating futures

std.lib.future wraps CompletableFuture with a Clojure-friendly API. future:call runs a function asynchronously, completed creates an already-done future, and incomplete creates a promise-like future.

create and complete futures

^{:refer std.lib.future/completed :added "3.0"}
@(completed 1)
=> 1

^{:refer std.lib.future/future:call :added "3.0"}
@(f/future:call (fn [] 1))
=> 1

^{:refer std.lib.future/incomplete :added "3.0"}
(f/future:incomplete? (incomplete))
=> true

2.2    Timeouts and values

future:timeout adds a timeout with an optional default. future:value blocks for the result, and future:now returns a default if not yet complete.

control future completion

^{:refer std.lib.future/future:timeout :added "3.0"}
@(-> (f/future:call (fn [] (Thread/sleep 100)))
     (f/future:timeout 10 :ok))
=> :ok

^{:refer std.lib.future/future:value :added "3.0"}
(-> (f/future:run (fn [] 1))
    (f/future:value))
=> 1

^{:refer std.lib.future/future:now :added "3.0"}
(-> (f/future:run (fn [] (Thread/sleep 100)))
    (f/future:now :invalid))
=> :invalid

2.3    Exception handling

Query and force completion states with future:exception, future:complete?, and future:force.

handle exceptional completion

^{:refer std.lib.future/future:exception :added "3.0"}
(-> (f/future:run (fn [] (throw (ex-info "ERROR" {}))))
    (f/future:exception))
=> Throwable

^{:refer std.lib.future/future:complete? :added "3.0"}
(f/future:complete? (completed 1))
=> true

3    API



*pools* ^

NONE
(defonce ^:dynamic *pools*
  (delay {:default  clojure.lang.Agent/soloExecutor
          :pooled   clojure.lang.Agent/pooledExecutor
          :async    (ForkJoinPool/commonPool)}))
link

catch ^

[future bindings & body]
Added 3.0

shortcut for :on/exception

v 3.0
(defmacro catch
  ([future bindings & body]
   (let [len (count bindings)]
     (case len
       0 `(on:exception  ~future (fn [~'_] ~@body))
       1 `(on:exception  ~future (fn [~@bindings] ~@body))))))
link
@(-> (f/future (+ 2 3)) (f/catch [e] e)) => 5 @(-> (f/future (throw (ex-info "" {:a 1}))) (f/catch [e] (ex-data e))) => {:a 1}

completed ^

[v]
Added 3.0

creates a completed stage

v 3.0
(defn completed
  ([v]
   (CompletableFuture/completedFuture v)))
link
@(completed 1) => 1

exception-fn ^

[f]

NONE
(defn- exception-fn
  ([f]
   (fn [v e]
     (cond e (f e) :else v))))
link

failed ^

[e]
Added 3.0

creates a failed stage

v 3.0
(defn failed
  ([e]
   (CompletableFuture/failedFuture e)))
link
@(failed (ex-info "" {})) => (throws)

fulfil ^

[future f] [future f print] [future f print skip-success]
Added 3.0

fulfils the return with a function

v 3.0
(defn fulfil
  ([future f]
   (fulfil future f false))
  ([future f print]
   (fulfil future f false false))
  ([future f print skip-success]
   (let [[status data exception] (try
                                   [:success (f) nil]
                                   (catch Throwable t
                                     (if print (.printStackTrace t))
                                     [:error nil t]))]
     (if-not (and (= status :success)
                  skip-success)
       (if (= status :success)
         (future:force future data)
         (future:force future :exception exception))
       data))))
link
(fulfil (incomplete) (fn [] (+ 1 2 3))) => future? (fulfil (incomplete) (fn [] (throw (ex-info "Hello" {})))) => future?

future ^

[] [opts? & body]
Added 3.0

constructs a completable future

v 3.0
(defmacro future
  ([]
   `(future:run (bound-fn []) {}))
  ([opts? & body]
   (let [[opts body] (cond (map? opts?) [opts? body]
                           :else [{} (cons opts? body)])]
     `(future:run (bound-fn [] ~@body)
                  ~opts))))
link
@(f/future (Thread/sleep 100) 1) => 1

future:call ^

[obj] [obj {:keys [pool delay], :as m}]
Added 3.0

can create a future from a function or :init/future

v 3.0
(defn ^CompletableFuture future:call
  ([obj]
   (future:call obj {}))
  ([obj {:keys [pool delay] :as m}]
   (let [[f m] (cond (fn? obj)
                     [obj m]

                     (instance? CompletableFuture obj)
                     (let [value (.get ^CompletableFuture obj)]
                       (if (and (map? value)
                                (:future/init (meta value)))
                         [(:fn value) (merge value m)]))

                     :else
                     (throw (ex-info "Not valid" {:data {:input obj
                                                         :args m}})))
         {:keys [pool delay]
          :or {pool :default}} m
         executor (if (keyword? pool)
                    (get @*pools* pool)
                    pool)]
     (cond (nil? delay)
           (CompletableFuture/supplyAsync (fn/fn:supplier [] (f)) executor)

           :else
           (let [executor (CompletableFuture/delayedExecutor delay
                                                             TimeUnit/MILLISECONDS
                                                             executor)]
             (CompletableFuture/supplyAsync (fn/fn:supplier [] (f)) executor))))))
link
@(f/future:call (fn [] 1)) => 1 @(-> (f/future:fn (fn [] 1)) (f/future:call)) => 1

future:cancel ^

[future]
Added 3.0

cancels the execution of the future

v 3.0
(defn ^CompletableFuture future:cancel
  ([^CompletableFuture future]
   (doto future (.cancel true))))
link
@(-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:cancel)) => (throws)

future:cancelled? ^

[future]
Added 3.0

checks if future has been cancelled

v 3.0
(defn future:cancelled?
  ([^CompletableFuture future]
   (future:done future (.isCancelled future))))
link
(-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:cancel) (f/future:cancelled?)) => true

future:chain ^

[future chain] [future chain marr]
Added 3.0

chains a set of functions

v 3.0
(defn future:chain
  ([future chain]
   (reduce (fn [out f]
             (on:complete out
                          (fn [data error]
                            (if error
                              (throw error)
                              (f data)))))
           future
           chain))
  ([future chain marr]
   (reduce (fn [out [f m]]
             (on:complete out
                          (fn [data error]
                            (if error
                              (throw error)
                              (f data)))
                          m))
           future
           (map vector chain marr))))
link
@(f/future:chain (completed 1) [inc inc inc]) => 4 @(f/future:chain (failed (ex-info "ERROR" {})) [inc inc inc]) => (throws)

future:complete? ^

[future]
Added 3.0

checks that future has successfully completed

v 3.0
(defn future:complete?
  ([^CompletableFuture future]
   (.isDone future)))
link
(-> (f/future:run (fn [] (throw (ex-info "Error" {})))) (f/future:wait) (f/future:success?)) => false (f/future:complete? (completed 1)) => true

future:dependents ^

[future]
Added 3.0

returns number of steps waiting on current result

v 3.0
(defn future:dependents
  ([^CompletableFuture future]
   (.getNumberOfDependents future)))
link
(-> (doto (f/future:run (fn [] (Thread/sleep 1000))) (on:complete (fn [e] e)) (on:complete (fn [e] e))) (f/future:dependents)) => 2

future:done ^

[future & body]
Added 3.0

helper macro for status functions

v 3.0
(defmacro future:done
  ([future & body]
   `(if-not (.isDone ~(with-meta future {:class CompletableFuture}))
      (throw (ex-info "Future not complete" {:future ~future}))
      (do ~@body))))
link
(f/future:done (completed 1) true) => true

future:exception ^

[future]
Added 3.0

accesses the exception in the future

v 3.0
(defn future:exception
  ([^CompletableFuture future]
   (try
     (.get future) nil
     (catch Throwable t t))))
link
(-> (f/future:run (fn [] (throw (ex-info "ERROR" {})))) (f/future:exception)) => Throwable

future:exception? ^

[future]
Added 3.0

checks if future raised an exception

v 3.0
(defn future:exception?
  ([^CompletableFuture future]
   (future:done future (.isCompletedExceptionally future))))
link
(-> (f/future:run (fn [] (throw (ex-info "Error" {})))) (f/future:wait) (f/future:exception?)) => true (-> (f/future:run (fn [] (Thread/sleep 1000))) (f/future:exception?)) => (throws)

future:fn ^

[f] [f {:keys [pool timeout delay default], :as m}]
Added 3.0

creates a future with :init/future props

v 3.0
(defn ^CompletableFuture future:fn
  ([f]
   (future:fn f {}))
  ([f {:keys [pool timeout delay default] :as m}]
   (doto (CompletableFuture.)
     (.complete (with-meta (merge {:fn f} m)
                  {:future/init true})))))
link
(.get (f/future:fn (fn [] 1))) => (contains {:fn fn?})

future:force ^

[future object] [future type object]
Added 3.0

forces a value or exception as completed future

v 3.0
(defn future:force
  ([^CompletableFuture future object]
   (future:force future :value object))
  ([^CompletableFuture future type object]
   (case type
     :value     (doto future (.complete object))
     :exception (doto future (.completeExceptionally object)))))
link
(-> (f/future:run (fn [] (Thread/sleep 1000))) (f/future:force 10) (f/future:value)) => 10 (-> (f/future:run (fn [] (Thread/sleep 1000))) (f/future:force 10) (f/future:complete?)) => true (-> (f/future:run (fn [] (Thread/sleep 1000))) (f/future:force :exception (ex-info "Error" {})) (f/future:exception?)) => true

future:incomplete? ^

[future]
Added 3.0

check that future is incomplete

v 3.0
(defn future:incomplete?
  ([^CompletableFuture future]
   (not (.isDone future))))
link
(-> (incomplete) (f/future:incomplete?)) => true

future:lift ^

[obj]
Added 3.0

creates a future from a value

v 3.0
(defn future:lift
  ([obj]
   (cond (nil? obj)
         (future:nil)

         (future? obj)
         obj

         :else
         (completed obj))))
link
(f/future? (f/future:lift (Object.))) => true

future:nil ^

NONE
(def future:nil
  (memoize (fn []
             (completed nil))))
link

future:now ^

[future] [future default]
Added 3.0

gets the value of a future at the current moment

v 3.0
(defn future:now
  ([^CompletableFuture future]
   (future:now future nil))
  ([^CompletableFuture future default]
   (.getNow future default)))
link
(-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:now :invalid)) => :invalid

future:obtrude ^

[future object] [future type object]
Added 4.0

like force but uses obtrude and obtrudeException

v 4.0
(defn future:obtrude
  ([^CompletableFuture future object]
   (future:obtrude future :value object))
  ([^CompletableFuture future type object]
   (case type
     :value     (doto future (.obtrudeValue object))
     :exception (doto future (.obtrudeException object)))))
link
(-> (f/future:run (fn [] (Thread/sleep 1000))) (f/future:obtrude 10) (f/future:value)) => 10

future:result ^

[future]
Added 3.0

gets the result of the future

v 3.0
(defn future:result
  ([future]
   (let [[status data exception]
         (if (and (future:wait future)
                  (future:exception? future))
           [:error nil (future:exception future)]
           [:success (future:value future) nil])]
     {:status status
      :data data
      :exception exception})))
link
(f/future:result (completed 1)) => {:status :success, :data 1, :exception nil} (f/future:result (failed (ex-info "" {}))) => (contains {:status :error :data nil :exception Throwable})

future:run ^

[obj] [obj {:keys [pool delay timeout default], :as m}]
Added 3.0

runs a function with additional settings

v 3.0
(defn ^CompletableFuture future:run
  ([obj]
   (future:run obj {}))
  ([obj {:keys [pool delay timeout default] :as m}]
   (-> (future:call obj m)
       (future:timeout timeout default))))
link
(f/future:run (fn [] (Thread/sleep 100)) {:timeout 10 :default :ok :delay 100 :pool :async}) => any?

future:status ^

[future]
Added 3.0

retrieves a status of either `:success`, `:error` or `waiting`

v 3.0
(defn future:status
  ([future]
   (cond (not (future-done? future))
         :waiting

         (future:exception? future)
         :error

         :else :success)))
link
(f/future:status (completed 1)) => :success

future:success? ^

[future]
Added 3.0

checks that future is successful

v 3.0
(defn future:success?
  ([^CompletableFuture future]
   (future:done future (not (.isCompletedExceptionally future)))))
link
(-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:wait) (f/future:success?)) => true (-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:success?)) => (throws)

future:timeout ^

[future interval] [future interval default]
Added 3.0

adds a timeout to the completed future

v 3.0
(defn ^CompletableFuture future:timeout
  ([^CompletableFuture future interval]
   (future:timeout future interval nil))
  ([^CompletableFuture future interval default]
   (cond (and (nil? interval)
              (nil? default))
         future

         (nil? default)
         (.orTimeout future interval TimeUnit/MILLISECONDS)

         :else
         (.completeOnTimeout future default interval TimeUnit/MILLISECONDS))))
link
@(-> (f/future:call (fn [] (Thread/sleep 100))) (f/future:timeout 10 :ok)) => :ok @(-> (f/future:call (fn [] (Thread/sleep 100))) (f/future:timeout 10)) => (throws)

future:timeout? ^

[future]
Added 3.0

checks if future errored due to timeout

v 3.0
(defn future:timeout?
  ([^CompletableFuture future]
   (future:done future
                (and (.isCompletedExceptionally future)
                     (instance? TimeoutException
                                (.getCause ^Throwable (future:exception future)))))))
link
(-> (f/future:run (fn [] (Thread/sleep 100))) (f/future:timeout 10) (f/future:wait) (f/future:timeout?)) => true

future:value ^

[future]
Added 3.0

gets the value of a future

v 3.0
(defn future:value
  ([^CompletableFuture future]
   (.get future)))
link
(-> (f/future:run (fn [] 1)) (f/future:value)) => 1

future:wait ^

[future] [future interval]
Added 3.0

waits for future to finish or

v 3.0
(defn ^CompletableFuture future:wait
  ([^CompletableFuture future]
   (try (doto future (.get))
        (catch Throwable t
          future)))
  ([^CompletableFuture future ^long interval]
   (Thread/sleep interval)
   future))
link
(-> (f/future:call (fn [] (Thread/sleep 100))) (f/future:timeout 10 :ok) (f/future:wait) (f/future:now)) => :ok

future? ^

[obj]
Added 3.0

checks if object is `CompleteableFuture`

v 3.0
(defn future?
  ([obj]
   (instance? CompletableFuture obj)))
link
(f/future? (f/future 1)) => true

incomplete ^

[]
Added 3.0

creates an incomplete stage (like promise)

v 3.0
(defn incomplete
  ([]
   (CompletableFuture.)))
link
(incomplete) => (comp not future:complete?)

on:all ^

[futures] [futures f] [futures f {:keys [timeout pool default delay], :as m}]
Added 3.0

calls a function when all futures are complete

v 3.0
(defn ^CompletableFuture on:all
  ([futures]
   (on:all futures vector))
  ([futures f]
   (on:all futures f {}))
  ([futures f {:keys [timeout pool default delay] :as m}]
   (let [futures (map future:lift futures)]
     (cond-> (into-array CompletableFuture futures)
       :then (CompletableFuture/allOf)
       f (on:complete (fn [_ _]
                        (apply f (map future:value futures)))
                      m)))))
link
@(on:all [(f/future 1) (f/future 2) (f/future 3)] (fn [a b c] (+ a b c))) => 6

on:any ^

[futures f] [futures f {:keys [timeout pool default delay], :as m}]
Added 3.0

calls a function when any future is completed

v 3.0
(defn ^CompletableFuture on:any
  ([futures f]
   (on:any futures f {}))
  ([futures f {:keys [timeout pool default delay] :as m}]
   (let [futures (map future:lift futures)
         select  (CompletableFuture/anyOf (into-array CompletableFuture
                                                      futures))]
     (on:complete select
                  (fn [_ _]
                    (f (future:value select)))
                  m))))
link
@(on:any [(f/future (Thread/sleep 500) 1) (f/future (Thread/sleep 500) 2) (f/future 3)] (fn [a] a)) => any

on:cancel ^

[future f] [future f m]
Added 3.0

processes a function on cancel

v 3.0
(defn ^CompletableFuture on:cancel
  ([^CompletableFuture future f]
   (on:cancel future f {}))
  ([^CompletableFuture future f m]
   (on:complete future (exception-fn
                        (fn [e]
                          (if (and e (instance? CancellationException e))
                            (f e)
                            (throw e))))
                m)))
link
@(-> (f/future {:timeout 10} (Thread/sleep 100)) (f/future:cancel) (on:cancel (fn [_] :cancel))) => :cancel @(-> (f/future {:timeout 10} (Thread/sleep 100)) (f/future:wait) (on:cancel (fn [_] :cancel))) => (throws)

on:complete ^

[future f] [future f {:keys [timeout pool default delay], :as m}]
Added 3.0

process both the value and exception

v 3.0
(defn ^CompletableFuture on:complete
  ([^CompletableFuture future f]
   (on:complete future f {}))
  ([^CompletableFuture future f {:keys [timeout pool default delay] :as m}]
   (let [bin-fn  (fn/fn:lambda [success error]
                               (f success (if error (or (.getCause ^Throwable error)
                                                        error))))
         executor (if pool
                    (if (keyword? pool)
                      (get @*pools* pool)
                      pool))

         executor (if delay
                    (CompletableFuture/delayedExecutor delay
                                                       TimeUnit/MILLISECONDS
                                                       (or executor (:default @*pools*)))
                    executor)
         nfuture (cond (nil? executor)
                       (.handle future
                                bin-fn)

                       :else (.handleAsync future bin-fn ^Executor executor))]
     (future:timeout nfuture timeout default))))
link
@(-> (f/future 1) (on:complete (fn [val _] (throw (ex-info "Error" {:val (inc val)})))) (on:complete (fn [_ err] (inc (:val (ex-data err))))) (on:complete (fn [val _] (inc val)))) => 4

on:exception ^

[future f] [future f {:keys [timeout pool default delay], :as m}]
Added 3.0

process a function on exception

v 3.0
(defn ^CompletableFuture on:exception
  ([^CompletableFuture future f]
   (on:exception future f {}))
  ([^CompletableFuture future f {:keys [timeout pool default delay] :as m}]
   (on:complete future (exception-fn (fn [e] (f e)))
                m)))
link
@(-> (f/future {:timeout 10} (Thread/sleep 100)) (f/future:cancel) (on:exception (fn [_] :cancel))) => :cancel @(-> (f/future {:timeout 10} (Thread/sleep 100)) (f/future:wait) (on:exception (fn [_] :timeout))) => :timeout @(-> (f/future (throw (ex-info "Error" {}))) (f/future:wait) (on:exception (fn [_] :exception))) => :exception

on:success ^

[future f] [future f {:keys [timeout pool default delay], :as m}]
Added 3.0

processes another step given successful operation

v 3.0
(defn ^CompletableFuture on:success
  ([^CompletableFuture future f]
   (on:success future f {}))
  ([^CompletableFuture future f {:keys [timeout pool default delay] :as m}]
   (on:complete future (fn [v e]
                         (if e (throw e) (f v)))
                m)))
link
@(-> (f/future 1) (on:success inc) (on:success inc) (on:success inc)) => 4

on:timeout ^

[future f] [future f {:keys [timeout pool default delay], :as m}]
Added 3.0

processes a function on timeout

v 3.0
(defn ^CompletableFuture on:timeout
  ([^CompletableFuture future f]
   (on:timeout future f {}))
  ([^CompletableFuture future f {:keys [timeout pool default delay] :as m}]
   (on:complete future (exception-fn
                        (fn [e]
                          (if (and e (instance? TimeoutException e))
                            (f e)
                            (throw e))))
                m)))
link
(-> (f/future (Thread/sleep 100)) (f/future:timeout 10) (on:timeout (fn [_] :timeout)) (f/future:wait) (f/future:value)) => :timeout @(-> (f/future {:timeout 10} (Thread/sleep 100)) (f/future:cancel) (on:timeout (fn [_] :timeout))) => (throws)

then ^

[future bindings & body]
Added 3.0

shortcut for :on/success and :on/complete

v 3.0
(defmacro then
  ([future bindings & body]
   (let [len (count bindings)]
     (case len
       0 `(on:success  ~future (fn [~'_] ~@body))
       1 `(on:success  ~future (fn [~@bindings] ~@body))
       2 `(on:complete ~future (fn [~@bindings] ~@body))))))
link
@(-> (f/future (+ 1 2 3)) (then [a] (+ a 1 2 3))) => 12 @(-> (f/future (throw (ex-info "Error" {:data 1}))) (then [a] (+ a 1 2 3)) (f/catch [ex] (ex-data ex))) => {:data 1} @(-> (f/future (+ 1 2 3)) (then [_ err] err)) => nil

4    std.lib.future: A Comprehensive Summary

The std.lib.future namespace provides a powerful and flexible abstraction for asynchronous and concurrent programming in Clojure, built upon Java's CompletableFuture. It offers a rich set of functions and macros for creating, managing, composing, and handling the results of asynchronous computations, including features for timeouts, cancellations, and exception handling.

Key Features and Concepts:

  1. Core Future Creation and Management:n *pools*: A delayed atom holding a map of java.util.concurrent.Executor instances (e.g., :default, :pooled, :async) for executing futures.n completed [v]: Creates a CompletableFuture that is already completed with a given value v.n failed [e]: Creates a CompletableFuture that is already completed exceptionally with a given Throwable e.n incomplete []: Creates a CompletableFuture that is not yet completed, similar to a Promise.n future? [obj]: A predicate to check if an object is a CompletableFuture.n future:fn [f & [m]]: Creates a CompletableFuture that holds a function f and optional metadata m, intended for later execution.n future:call [obj & [m]]: Executes a function obj (or a future:fn object) asynchronously, returning a CompletableFuture. It supports specifying an executor pool and a delay.n future:timeout [future interval & [default]]: Adds a timeout to a CompletableFuture. If the future doesn't complete within interval milliseconds, it either completes exceptionally with a TimeoutException or with a default value.n future:wait [future & [interval]]: Blocks the current thread until the future completes. Optionally waits for a specified interval before returning the future.n future:run [obj & [m]]: A high-level function to run an asynchronous computation with options for pool, delay, timeout, and default value.n future:now [future & [default]]: Attempts to get the value of the future immediately without blocking. If not complete, returns default or throws an exception.n future:value [future]: Blocks and returns the result of the future.n future:exception [future]: Blocks and returns the exception if the future completed exceptionally, otherwise nil.n future:cancel [future]: Attempts to cancel the execution of the future.n future:done [future & body]: A macro that ensures a future is complete before executing body, otherwise throws an exception.n future:cancelled? [future]: Checks if the future was cancelled.n future:exception? [future]: Checks if the future completed exceptionally.n future:timeout? [future]: Checks if the future completed exceptionally due to a TimeoutException.n future:success? [future]: Checks if the future completed successfully (not exceptionally).n future:incomplete? [future]: Checks if the future is still running (not yet completed).n future:complete? [future]: Checks if the future has completed (either successfully or exceptionally).n future:force [future type object]: Forces a future to complete with a given object (either as a :value or an :exception).n future:obtrude [future type object]: Similar to future:force but uses obtrudeValue and obtrudeException, which can overwrite existing results.n future:dependents [future]: Returns the number of dependent stages waiting on the future's completion.n future:nil []: A memoized function that returns a completed future with nil.n future:lift [obj]: Lifts a plain value or an existing CompletableFuture into a CompletableFuture.nn2. Future Composition and Callbacks (on: functions):n on:complete [future f & [m]]: Attaches a callback f to be executed when the future completes, regardless of success or failure. The callback receives both the result and any exception.n on:timeout [future f & [m]]: Attaches a callback f to be executed specifically if the future times out.n on:cancel [future f & [m]]: Attaches a callback f to be executed specifically if the future is cancelled.n on:exception [future f & [m]]: Attaches a callback f to be executed specifically if the future completes exceptionally (for any exception).n on:success [future f & [m]]: Attaches a callback f to be executed only if the future completes successfully.n on:all [futures & [f m]]: Creates a new CompletableFuture that completes when all input futures have completed. An optional function f can process their results.n on:any [futures f & [m]]: Creates a new CompletableFuture that completes when any of the input futures completes. An optional function f can process the result of the first completed future.nn3. Macros for Asynchronous Flow Control:n future [& opts? body]: A macro that wraps future:run to provide a more idiomatic way to define asynchronous blocks of code.n then [future bindings & body]: A macro that provides a convenient syntax for chaining successful operations (on:success) or handling both success and failure (on:complete).n catch [future bindings & body]: A macro that provides a convenient syntax for handling exceptions (on:exception).nn4. Result Handling and Status:n fulfil [future f & [print skip-success]]: Attempts to complete an incomplete future by executing a function f. It handles both successful results and exceptions, optionally printing stack traces.n future:result [future]: Returns a map describing the final status of a future (:success, :error), its data, and any exception.n future:status [future]: Returns a keyword indicating the current status of a future (:waiting, :success, :error).n future:chain [future chain & [marr]]: Chains a sequence of functions (chain) to be executed sequentially on the result of a future, each step returning a new future.

Overall Importance:

The std.lib.future module is a cornerstone for building responsive, scalable, and fault-tolerant applications within the foundation-base project. Its key contributions include:

  • Simplified Asynchronous Programming: Provides a high-level, idiomatic Clojure API over CompletableFuture, making it easier to write and reason about asynchronous code.n Robust Concurrency Control: Offers fine-grained control over execution (executors, delays, timeouts) and robust exception handling mechanisms.n Powerful Composition: The on: functions and then/catch macros enable complex asynchronous workflows to be built by composing smaller, independent futures.n Improved Responsiveness: Allows long-running computations to be offloaded to background threads, preventing UI freezes or blocking of critical operations.n Error Resilience: Built-in support for timeouts, cancellations, and structured exception handling helps in creating more resilient systems.

By offering these comprehensive asynchronous programming capabilities, std.lib.future significantly enhances the foundation-base project's ability to manage complex, concurrent tasks, which is vital for its multi-language transpilation and runtime management goals.