Skip to content
Browse files

[#55,#56] add clojure.core.async

  • Loading branch information...
borkdude committed Sep 7, 2019
1 parent 93f1542 commit 5ca10617d30031bc0c7718012ad2a55633d2dc09
Showing with 143 additions and 9 deletions.
  1. +34 −0
  2. +2 −1 project.clj
  3. +68 −0 src/babashka/impl/async.clj
  4. +23 −5 src/babashka/impl/clojure/core.clj
  5. +6 −2 src/babashka/main.clj
  6. +10 −1 test/babashka/main_test.clj
@@ -131,6 +131,9 @@ explicitly.
- `sh`
- `` aliased as `io`:
- `as-relative-path`, `copy`, `delete-file`, `file`
- [`clojure.core.async`]( aliased as
`async`. The `alt` and `go` macros are not available but `alts!!` does work as
it is a function.
- [`me.raynes.conch.low-level`](
aliased as `conch`

@@ -164,6 +167,20 @@ Waits for TCP connection to be available on host and port. Options map supports
`:timeout` and `:pause`. If `:timeout` is provided and reached, exception will
be thrown. The `:pause` option determines the time waited between retries.
- `sig/pipe-signal-received?`. Usage:
``` clojure
Returns true if `PIPE` signal was received. Example:
``` shellsession
$ bb '((fn [x] (println x) (when (not (sig/pipe-signal-received?)) (recur (inc x)))) 0)' | head -n2
## Examples
``` shellsession
@@ -308,6 +325,23 @@ $ bb '
(net/wait-for-it "localhost" 1777) (conch/destroy ws)'
## Async
Apart from `future` for creating threads and the `conch` namespace for creating
processes, you may use `core.async` to script asynchronously. The following
example shows how to get first available value from two different processes:
``` clojure
bb '
(defn async-command [& args]
(async/thread (apply shell/sh "bash" "-c" args)))
(-> (async/alts!! [(async-command "sleep 2 && echo process 1")
(async-command "sleep 1 && echo process 2")])
first :out str/trim println)'
process 2
## Enabling SSL
If you want to be able to use SSL to e.g. run `(slurp
@@ -9,7 +9,8 @@
:url ""}
:source-paths ["src" "sci/src" "sci/inlined" "conch/src"]
:resource-paths ["resources" "sci/resources"]
:dependencies [[org.clojure/clojure "1.10.1"]]
:dependencies [[org.clojure/clojure "1.10.1"]
[org.clojure/core.async "0.4.500"]]
:profiles {:test {:dependencies [[clj-commons/conch "0.9.2"]]}
:uberjar {:global-vars {*assert* false}
:jvm-opts [""
@@ -0,0 +1,68 @@
(ns babashka.impl.async
{:no-doc true}
(:require [clojure.core.async :as async]))

(defn thread
[& body]
`(~'async/thread-call (fn [] ~@body)))

(def async-bindings
{'async/<!! async/<!!
'async/>!! async/>!!
'async/admix async/admix
'async/alts! async/alts!
'async/alts!! async/alts!!
'async/buffer async/buffer
'async/chan async/chan
'async/close! async/close!
'async/do-alt async/do-alt
'async/do-alts async/do-alts
'async/dropping-buffer async/dropping-buffer
'async/filter< async/filter<
'async/filter> async/filter>
'async/into async/into
'async/map async/map
'async/map< async/map<
'async/map> async/map>
'async/mapcat< async/mapcat<
'async/mapcat> async/mapcat>
'async/merge async/merge
'async/mix async/mix
'async/mult async/mult
'async/offer! async/offer!
'async/onto-chan async/onto-chan
'async/partition async/partition
'async/partition-by async/partition-by
'async/pipe async/pipe
'async/pipeline async/pipeline
'async/pipeline-async async/pipeline-async
'async/pipeline-blocking async/pipeline-blocking
'async/poll! async/poll!
'async/promise-chan async/promise-chan
'async/pub async/pub
'async/put! async/put!
'async/reduce async/reduce
'async/remove< async/remove<
'async/remove> async/remove>
'async/sliding-buffer async/sliding-buffer
'async/solo-mode async/solo-mode
'async/split async/split
'async/sub async/sub
'async/take async/take
'async/take! async/take!
'async/tap async/tap
'async/thread (with-meta thread {:sci/macro true})
'async/thread-call async/thread-call
'async/timeout async/timeout
'async/to-chan async/to-chan
'async/toggle async/toggle
'async/transduce async/transduce
'async/unblocking-buffer? async/unblocking-buffer?
'async/unique async/unique
'async/unmix async/unmix
'async/unmix-all async/unmix-all
'async/unsub async/unsub
'async/unsub-all async/unsub-all
'async/untap async/untap
'async/untap-all async/untap-all})

@@ -10,17 +10,35 @@
{;; atoms
'atom atom
'swap! swap!
'swap-vals! swap-vals!
'reset! reset!
'add-watch add-watch

'future-call future-call
'future (with-meta future {:sci/macro true})
'future-cancel future-cancel
'future-cancelled? future-cancelled?
'future-done? future-done?
'future? future?
'deref deref
'agent agent
'send send
'send-off send-off
'promise promise
'deliver deliver
'shutdown-agents shutdown-agents
'run! run!
'slurp slurp
'spit spit
'pmap pmap
'print print
'pr pr
'pr-str pr-str
'prn prn
'prn-str prn-str
'print-str print-str
'print print
'println println
'future-call future-call
'future (with-meta future {:sci/macro true})
'deref deref})
'println-str println-str
'flush flush
'ex-info ex-info
'ex-data ex-data
@@ -4,6 +4,7 @@
[babashka.impl.File :refer [file-bindings]]
[babashka.impl.System :refer [system-bindings]]
[babashka.impl.Thread :refer [thread-bindings]]
[babashka.impl.async :refer [async-bindings]]
[babashka.impl.clojure.core :refer [core-bindings]]
[babashka.impl.clojure.stacktrace :refer [print-stack-trace]]
[babashka.impl.conch :refer [conch-bindings]]
@@ -147,12 +148,14 @@ Everything after that is bound to *command-line-args*."))
'io/file io/file
'io/reader io/reader
'edn/read-string edn/read-string
'net/wait-for-it net/wait-for-it}
'net/wait-for-it net/wait-for-it
'sig/pipe-signal-received? pipe-signal-received?}

(defn read-edn []
(edn/read {;;:readers *data-readers*
@@ -244,6 +247,7 @@ Everything after that is bound to *command-line-args*."))
t1 (System/currentTimeMillis)]
(when time? (binding [*out* *err*]
(println "bb took" (str (- t1 t0) "ms."))))

(defn -main
@@ -129,7 +129,7 @@
(let [tmp ( "script" ".clj")]
(spit tmp "(defn foo [x y] (+ x y)) (defn bar [x y] (* x y))")
(is (= "120\n" (test-utils/bb nil (format "(load-file \"%s\") (bar (foo 10 30) 3)"
(.getPath tmp)))))))
(.getPath tmp)))))))

(deftest preloads-test
@@ -176,3 +176,12 @@
(net/wait-for-it \"\" 7171)
(conch/destroy web-server)
(net/wait-for-it \"localhost\" 7172 {:timeout 50})"))))

(deftest async-test
(is (= "process 2\n" (test-utils/bb nil "
(defn async-command [& args]
(async/thread (apply shell/sh \"bash\" \"-c\" args)))
(-> (async/alts!! [(async-command \"sleep 2 && echo process 1\")
(async-command \"sleep 1 && echo process 2\")])
first :out str/trim println)"))))

0 comments on commit 5ca1061

Please sign in to comment.
You can’t perform that action at this time.