Back
future-call (clj)
(source)function
(future-call f)
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?.
Examples
clojure/core.typed
(ns ^:skip-wiki clojure.core.typed.ann.clojure
"Type annotations for the base Clojure distribution."
(:require [#?(:clj clojure.core.typed
:cljs cljs.core.typed)
:refer [defalias] :as t]))
(defalias
^{:doc "A Clojure future (see clojure.core/{future-call,future})."
:forms '[(Future t)]}
t/Future
(t/TFn [[x :variance :covariant]]
(t/I (t/Deref x)
(clojure.lang.IBlockingDeref x)
clojure.lang.IPending
java.util.concurrent.Future)))
hraberg/deuce
(ns deuce.emacs.callproc
(:use [deuce.emacs-lisp :only (defun defvar) :as el])
(:require [clojure.core :as c]
[clojure.string :as s]
[clojure.java.io :as io]
[clojure.java.shell :as sh]
[deuce.emacs.buffer :as buffer]
[deuce.emacs.data :as data]
[deuce.emacs.editfns :as editfns])
(:import [java.io File])
(:refer-clojure :exclude []))
If BUFFER is 0, `call-process' returns immediately with value nil.
Otherwise it waits for PROGRAM to terminate
and returns a numeric exit status or a signal description string.
If you quit, the process is killed with SIGINT, or SIGKILL if you quit again."
(let [opts (if infile [:in (io/file infile)] [])
no-wait? (= 0 buffer)
buffer (or no-wait?
(and (data/consp buffer) (= :file (data/car buffer)) (data/cdr buffer))
(and (true? buffer) (buffer/current-buffer))
(el/check-type 'bufferp (or (when (data/consp buffer) (data/car buffer))
buffer (buffer/current-buffer))))
stderr (when (data/consp buffer) (data/cdr buffer))
runner (if no-wait? #(do (future-call %) nil) #(%))]
(runner #(let [{:keys [exit out err]}
(apply sh/sh (concat (cons program args) opts))]
(when (data/bufferp buffer)
(binding [buffer/*current-buffer* buffer]
(editfns/insert out)
(when (true? stderr)
(editfns/insert err))))
(when (string? buffer)
(spit (io/file buffer) out))
(when (string? stderr)
(spit (io/file stderr) err))
exit))))
typedclojure/typedclojure
(ns ^:no-doc typed.ann.clojure
"Type annotations for the base Clojure distribution."
#?(:cljs (:require-macros [typed.ann-macros.clojure :as macros]))
(:require [clojure.core :as cc]
[typed.clojure :as t]
#?(:clj [typed.ann-macros.clojure :as macros])
#?(:clj typed.ann.clojure.jvm) ;; jvm annotations
#?(:clj clojure.core.typed))
#?(:clj
(:import (clojure.lang PersistentHashSet PersistentList
APersistentMap #_IPersistentCollection
#_ITransientSet
IRef)
(java.util Comparator Collection))))
#?(:clj
(t/defalias
^{:doc "A Clojure future (see clojure.core/{future-call,future})."
:forms '[(Future x)]}
t/Future
(t/TFn [[x :variance :covariant]]
(t/I (t/Deref x)
(clojure.lang.IBlockingDeref x)
clojure.lang.IPending
java.util.concurrent.Future))))
#?@(:cljs [] :default [
cc/future-call (t/All [x] [[:-> x] :-> (t/Future x)])
])
ReactiveX/RxClojure
(ns rx.lang.clojure.graph-test
(:require [rx.lang.clojure.graph :as graph]
[rx.lang.clojure.core :as rx]
[rx.lang.clojure.future :as rx-future]
[rx.lang.clojure.blocking :as rx-blocking]
[clojure.test :refer [deftest testing is]]))
(testing "it still works"
(is (= {:a 99 :b 100 :z "hi"}
(rx-blocking/single
(-> (let [z (rx/return "hi")] ; an observable from "somewhere else"
(graph/let-o
[?a (rx-future/future* future-call #(do (Thread/sleep 50) 99))
?b (rx-future/future* future-call #(do (Thread/sleep 500) 100))
?c (rx/map #(hash-map :a %1 :b %2 :z %3) ?a ?b ?z)
?z z]
(rx/reduce merge {} ?c)))))))))
(deftest test-complicated-graph
; These funcs model network requests for various stuff. They all return observable.
(let [request-vhs (fn []
(rx-future/future-generator*
future-call
(fn [o]
(Thread/sleep 50)
(doseq [i (range 3)]
(rx/on-next o {:id i})))))
request-user (fn [id]
(rx-future/future*
future-call
#(do (Thread/sleep (rand-int 250))
{:id id
:name (str "friend" id) })))
request-ab (fn [u]
(rx-future/future*
future-call
#(do (Thread/sleep (rand-int 250))
{:user-id (:id u)
:cell (* 2 (:id u))})))
; Now we can stitch all these requests together into an rx graph to
; produce a response.
o (graph/let-o [?user-info (rx-future/future*
future-call
#(do (Thread/sleep 20)
{:name "Bob"
:id 12345
:friend-ids [1 2 3] }))
ReactiveX/RxClojure
(ns rx.lang.clojure.core-test
(:require [rx.lang.clojure.core :as rx]
[rx.lang.clojure.blocking :as b]
[rx.lang.clojure.future :as f]
[clojure.test :refer [deftest is testing are]]))
(let [expected-result [[1 3 5] [2 4 6]]
sleepy-o #(f/future-generator*
future-call
(fn [o]
(doseq [x %]
(Thread/sleep 10)
(rx/on-next o x))))
make-inputs (fn [] (mapv sleepy-o expected-result))
make-output (fn [r] [(keep #{1 3 5} r)
(keep #{2 4 6} r)])]
(deftest test-merge*
(is (= expected-result
(->> (make-inputs)
(rx/seq->o)
(rx/merge*)
(b/into [])
(make-output)))))
(deftest test-merge
(is (= expected-result
(->> (make-inputs)
(apply rx/merge)
(b/into [])
(make-output)))))
(deftest test-merge-delay-error*
(is (= expected-result
(->> (make-inputs)
(rx/seq->o)
(rx/merge-delay-error*)
(b/into [])
(make-output)))))
(deftest test-merge-delay-error
(is (= expected-result
(->> (make-inputs)
(apply rx/merge-delay-error)
(b/into [])
(make-output))))))