Merge pull request #48 from imrekoszo/fixes-2022-07
Fix various bugs, add deps.edn, support babashka
This commit is contained in:
commit
516b8b6306
11 changed files with 222 additions and 49 deletions
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/clojure
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=clojure
|
||||||
|
|
||||||
|
### Clojure ###
|
||||||
|
pom.xml
|
||||||
|
pom.xml.asc
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
/lib/
|
||||||
|
/classes/
|
||||||
|
/target/
|
||||||
|
/checkouts/
|
||||||
|
.lein-deps-sum
|
||||||
|
.lein-repl-history
|
||||||
|
.lein-plugins/
|
||||||
|
.lein-failures
|
||||||
|
.nrepl-port
|
||||||
|
.cpcache/
|
||||||
|
.clj-kondo/*/
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/clojure
|
||||||
14
README.md
14
README.md
|
|
@ -232,6 +232,20 @@ Evaluation count : 24 in 6 samples of 4 calls.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### Unreleased
|
||||||
|
|
||||||
|
* Add `deps.edn` to enable usage as a [git library](https://clojure.org/guides/deps_and_cli#_using_git_libraries)
|
||||||
|
* Bump `macrovich` to make Clojure and ClojureScript provided dependencies #34
|
||||||
|
* Fix reflection warnings in `xforms.io` #35 #36
|
||||||
|
* Add compatibility with [babashka](https://github.com/babashka/babashka) #42
|
||||||
|
* Fix `x/destructuring-pair?` #44 #45
|
||||||
|
* Fix `x/into` performance hit with small maps #46 #47
|
||||||
|
* Fix reflection and shadowing warnings in tests
|
||||||
|
|
||||||
|
### 0.19.2
|
||||||
|
|
||||||
|
* Fix infinity symbol causing issues with ClojureScript #31
|
||||||
|
|
||||||
### 0.19.0
|
### 0.19.0
|
||||||
|
|
||||||
`time` allows to measure time spent in one transducer (excluding time spent downstream).
|
`time` allows to measure time spent in one transducer (excluding time spent downstream).
|
||||||
|
|
|
||||||
37
bb.edn
Normal file
37
bb.edn
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{:deps {local/deps {:local/root "."}}
|
||||||
|
:paths ["src" "test"]
|
||||||
|
|
||||||
|
:tasks
|
||||||
|
{:init
|
||||||
|
(do
|
||||||
|
(defn kaocha [alias args]
|
||||||
|
(apply shell "bin/kaocha" alias args)))
|
||||||
|
|
||||||
|
test-9
|
||||||
|
{:task (kaocha :clj-1-9 *command-line-args*)}
|
||||||
|
|
||||||
|
test-10
|
||||||
|
{:task (kaocha :clj-1-10 *command-line-args*)}
|
||||||
|
|
||||||
|
test-11
|
||||||
|
{:task (kaocha :clj-1-11 *command-line-args*)}
|
||||||
|
|
||||||
|
test-clj
|
||||||
|
{:task (doseq [alias [:clj-1-9 :clj-1-10 :clj-1-11]]
|
||||||
|
(kaocha alias *command-line-args*))}
|
||||||
|
|
||||||
|
test-bb
|
||||||
|
{:requires ([clojure.test :as t]
|
||||||
|
[net.cgrand.xforms-test])
|
||||||
|
:task (t/run-tests 'net.cgrand.xforms-test)}
|
||||||
|
|
||||||
|
perf-bb
|
||||||
|
{:requires ([net.cgrand.xforms :as x])
|
||||||
|
:task
|
||||||
|
(let [n 10000
|
||||||
|
m (zipmap (range 100) (range))
|
||||||
|
mapping (map (fn [[k v]] [k (inc v)]))
|
||||||
|
xforing (x/for [[k v] _] [k (inc v)])]
|
||||||
|
(time (dotimes [_ n] (into {} mapping m)))
|
||||||
|
(time (dotimes [_ n] (into {} xforing m)))
|
||||||
|
(time (dotimes [_ n] (x/into {} xforing m))))}}}
|
||||||
3
bin/kaocha
Executable file
3
bin/kaocha
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -x
|
||||||
|
clojure -Srepro -M:kaocha:test"$1" "${@:2}"
|
||||||
28
deps.edn
Normal file
28
deps.edn
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{:deps {net.cgrand/macrovich {:mvn/version "0.2.1"}}
|
||||||
|
:paths ["src"]
|
||||||
|
|
||||||
|
:aliases
|
||||||
|
{:dev
|
||||||
|
{:extra-paths ["dev"]}
|
||||||
|
|
||||||
|
:clj-1-9
|
||||||
|
{:extra-deps
|
||||||
|
{org.clojure/clojure {:mvn/version "1.9.0"}
|
||||||
|
org.clojure/clojurescript {:mvn/version "1.9.293"}}}
|
||||||
|
|
||||||
|
:clj-1-10
|
||||||
|
{:extra-deps
|
||||||
|
{org.clojure/clojure {:mvn/version "1.10.3"}
|
||||||
|
org.clojure/clojurescript {:mvn/version "1.10.914"}}}
|
||||||
|
|
||||||
|
:clj-1-11
|
||||||
|
{:extra-deps
|
||||||
|
{org.clojure/clojure {:mvn/version "1.11.1"}
|
||||||
|
org.clojure/clojurescript {:mvn/version "1.11.60"}}}
|
||||||
|
|
||||||
|
:test
|
||||||
|
{:extra-paths ["test"]}
|
||||||
|
|
||||||
|
:kaocha
|
||||||
|
{:extra-deps {lambdaisland/kaocha {:mvn/version "1.69.1069"}}
|
||||||
|
:main-opts ["-m" "kaocha.runner"]}}}
|
||||||
3
dev/user.clj
Normal file
3
dev/user.clj
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
(ns user)
|
||||||
|
|
||||||
|
(set! *warn-on-reflection* true)
|
||||||
14
project.clj
14
project.clj
|
|
@ -1,8 +1,14 @@
|
||||||
(defproject net.cgrand/xforms "0.19.2"
|
(defproject net.cgrand/xforms "0.19.3-SNAPSHOT"
|
||||||
:description "Extra transducers for Clojure"
|
:description "Extra transducers for Clojure"
|
||||||
:url "https://github.com/cgrand/xforms"
|
:url "https://github.com/cgrand/xforms"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||||
:dependencies [[org.clojure/clojure "1.8.0" :scope "provided"]
|
|
||||||
[org.clojure/clojurescript "1.9.293" :scope "provided"]
|
:plugins [[lein-tools-deps "0.4.5"]]
|
||||||
[net.cgrand/macrovich "0.2.0"]])
|
:middleware [lein-tools-deps.plugin/resolve-dependencies-with-deps-edn]
|
||||||
|
:lein-tools-deps/config {:config-files [:project]}
|
||||||
|
|
||||||
|
:profiles
|
||||||
|
{:provided
|
||||||
|
{:dependencies [[org.clojure/clojure "1.8.0"]
|
||||||
|
[org.clojure/clojurescript "1.9.293"]]}})
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
:clj (:require [net.cgrand.macrovich :as macros]))
|
:clj (:require [net.cgrand.macrovich :as macros]))
|
||||||
(:refer-clojure :exclude [some reduce reductions into count for partition
|
(:refer-clojure :exclude [some reduce reductions into count for partition
|
||||||
str last keys vals min max drop-last take-last
|
str last keys vals min max drop-last take-last
|
||||||
sort sort-by time])
|
sort sort-by time satisfies?])
|
||||||
(:require [#?(:clj clojure.core :cljs cljs.core) :as core]
|
(:require [#?(:clj clojure.core :cljs cljs.core) :as core]
|
||||||
[net.cgrand.xforms.rfs :as rf])
|
[net.cgrand.xforms.rfs :as rf]
|
||||||
|
#?(:clj [clojure.core.protocols]))
|
||||||
#?(:cljs (:import [goog.structs Queue])))
|
#?(:cljs (:import [goog.structs Queue])))
|
||||||
|
|
||||||
(macros/deftime
|
(macros/deftime
|
||||||
|
|
@ -28,8 +29,10 @@
|
||||||
(unreduced-> (-> x# ~expr) ~@exprs)))))
|
(unreduced-> (-> x# ~expr) ~@exprs)))))
|
||||||
|
|
||||||
(defn- pair? [x] (and (vector? x) (= 2 (core/count x))))
|
(defn- pair? [x] (and (vector? x) (= 2 (core/count x))))
|
||||||
(defn- destructuring-pair? [x]
|
(let [kw-or-& #(or (keyword? %) (= '& %))]
|
||||||
(and (pair? x) (not (or (keyword? x) (= '& x)))))
|
(defn- destructuring-pair? [x]
|
||||||
|
(and (pair? x)
|
||||||
|
(not (kw-or-& (first x))))))
|
||||||
|
|
||||||
(defmacro for
|
(defmacro for
|
||||||
"Like clojure.core/for with the first expression being replaced by % (or _). Returns a transducer.
|
"Like clojure.core/for with the first expression being replaced by % (or _). Returns a transducer.
|
||||||
|
|
@ -99,7 +102,8 @@
|
||||||
(not (arities 2)) (conj (let [[[acc karg varg] & body] (arities 3)]
|
(not (arities 2)) (conj (let [[[acc karg varg] & body] (arities 3)]
|
||||||
`([~acc [~karg ~varg]] ~@body))))]
|
`([~acc [~karg ~varg]] ~@body))))]
|
||||||
`(reify
|
`(reify
|
||||||
~@(macros/case :clj '[clojure.lang.Fn])
|
#?@(:bb [] ;; babashka currently only supports reify with one Java interface at a time
|
||||||
|
:default [~@(macros/case :clj '[clojure.lang.Fn])])
|
||||||
KvRfable
|
KvRfable
|
||||||
(some-kvrf [this#] this#)
|
(some-kvrf [this#] this#)
|
||||||
~(macros/case :cljs `core/IFn :clj 'clojure.lang.IFn)
|
~(macros/case :cljs `core/IFn :clj 'clojure.lang.IFn)
|
||||||
|
|
@ -124,8 +128,44 @@
|
||||||
|
|
||||||
(macros/usetime
|
(macros/usetime
|
||||||
|
|
||||||
(defn kvreducible? [coll]
|
;; Workaround clojure.core/satisfies? being slow in Clojure
|
||||||
(satisfies? #?(:clj clojure.core.protocols/IKVReduce :cljs IKVReduce) coll))
|
;; see https://ask.clojure.org/index.php/3304/make-satisfies-as-fast-as-a-protocol-method-call
|
||||||
|
#?(:cljs
|
||||||
|
(def satisfies? core/satisfies?)
|
||||||
|
|
||||||
|
:bb
|
||||||
|
(def satisfies? core/satisfies?)
|
||||||
|
|
||||||
|
:clj
|
||||||
|
(defn fast-satisfies?-fn
|
||||||
|
"Ported from https://github.com/clj-commons/manifold/blob/37658e91f836047a630586a909a2e22debfbbfc6/src/manifold/utils.clj#L77-L89"
|
||||||
|
[protocol-var]
|
||||||
|
(let [^java.util.concurrent.ConcurrentHashMap classes
|
||||||
|
(java.util.concurrent.ConcurrentHashMap.)]
|
||||||
|
(add-watch protocol-var ::memoization (fn [& _] (.clear classes)))
|
||||||
|
(fn [x]
|
||||||
|
(let [cls (class x)
|
||||||
|
val (.get classes cls)]
|
||||||
|
(if (nil? val)
|
||||||
|
(let [val (core/satisfies? @protocol-var x)]
|
||||||
|
(.put classes cls val)
|
||||||
|
val)
|
||||||
|
val))))))
|
||||||
|
|
||||||
|
|
||||||
|
#?(:cljs
|
||||||
|
(defn kvreducible? [coll]
|
||||||
|
(satisfies? core/IKVReduce coll))
|
||||||
|
|
||||||
|
:clj
|
||||||
|
(let [satisfies-ikvreduce? #?(:bb #(satisfies? clojure.core.protocols/IKVReduce %)
|
||||||
|
:default (fast-satisfies?-fn #'clojure.core.protocols/IKVReduce))]
|
||||||
|
(if (satisfies-ikvreduce? (Object.))
|
||||||
|
(defn kvreducible?
|
||||||
|
"Clojure 1.11 makes everything satisfy IKVReduce, so we can short-circuit"
|
||||||
|
[_] true)
|
||||||
|
(defn kvreducible? [coll] (satisfies-ikvreduce? coll)))))
|
||||||
|
|
||||||
|
|
||||||
(extend-protocol KvRfable
|
(extend-protocol KvRfable
|
||||||
#?(:clj Object :cljs default) (some-kvrf [_] nil)
|
#?(:clj Object :cljs default) (some-kvrf [_] nil)
|
||||||
|
|
@ -556,7 +596,7 @@
|
||||||
"Iterator transducing context, returns an iterator on the transformed data.
|
"Iterator transducing context, returns an iterator on the transformed data.
|
||||||
Equivalent to (.iterator (eduction xform (iterator-seq src-iterator))) except there's is no buffering on values (as in iterator-seq),
|
Equivalent to (.iterator (eduction xform (iterator-seq src-iterator))) except there's is no buffering on values (as in iterator-seq),
|
||||||
This buffering may cause problems when mutable objects are returned by the src-iterator."
|
This buffering may cause problems when mutable objects are returned by the src-iterator."
|
||||||
[xform ^java.util.Iterator src-iterator]
|
^java.util.Iterator [xform ^java.util.Iterator src-iterator]
|
||||||
(let [NULL (Object.)
|
(let [NULL (Object.)
|
||||||
dq (java.util.ArrayDeque. 32)
|
dq (java.util.ArrayDeque. 32)
|
||||||
rf (xform (fn ([acc] acc) ([acc x] (.push dq (if (some? x) x NULL)) acc)))
|
rf (xform (fn ([acc] acc) ([acc x] (.push dq (if (some? x) x NULL)) acc)))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
(ns net.cgrand.xforms.io
|
(ns net.cgrand.xforms.io
|
||||||
(:require [clojure.java.io :as io]
|
(:require [clojure.java.io :as io]
|
||||||
[clojure.java.shell :as sh]
|
[clojure.java.shell :as sh]
|
||||||
[clojure.edn :as edn]))
|
[clojure.edn :as edn])
|
||||||
|
(:import (java.io Reader BufferedReader IOException InputStream OutputStream BufferedWriter Writer PushbackReader InputStreamReader OutputStreamWriter Closeable)
|
||||||
|
(java.util Arrays List)
|
||||||
|
(java.util.concurrent ArrayBlockingQueue)
|
||||||
|
(java.lang ProcessBuilder$Redirect)
|
||||||
|
(clojure.lang IFn Fn IReduce)))
|
||||||
|
|
||||||
(defn keep-opts [m like]
|
(defn keep-opts [m like]
|
||||||
(let [ns (namespace like)]
|
(let [ns (namespace like)]
|
||||||
|
|
@ -17,11 +22,11 @@
|
||||||
Input is automatically closed upon completion or error."
|
Input is automatically closed upon completion or error."
|
||||||
[in & opts]
|
[in & opts]
|
||||||
(let [no-init (Object.)]
|
(let [no-init (Object.)]
|
||||||
(reify clojure.lang.IReduce
|
(reify IReduce
|
||||||
(reduce [self f] (.reduce self f no-init))
|
(reduce [self f] (.reduce self f no-init))
|
||||||
(reduce [self f init]
|
(reduce [self f init]
|
||||||
(with-open [rdr (apply io/reader in opts)]
|
(with-open [^Reader rdr (apply io/reader in opts)]
|
||||||
(let [rdr (cond-> rdr (not (instance? java.io.BufferedReader rdr)) java.io.BufferedReader.)
|
(let [^BufferedReader rdr (cond-> rdr (not (instance? BufferedReader rdr)) (BufferedReader.))
|
||||||
init (if (identical? init no-init)
|
init (if (identical? init no-init)
|
||||||
(or (.readLine rdr) (f))
|
(or (.readLine rdr) (f))
|
||||||
init)]
|
init)]
|
||||||
|
|
@ -34,17 +39,17 @@
|
||||||
state))))))))
|
state))))))))
|
||||||
|
|
||||||
(defn lines-out
|
(defn lines-out
|
||||||
"1-2 args: reducing function that writes values serialized to its accumulator (a java.io.Writer).
|
"1-2 args: reducing function that writes values serialized to its accumulator (a java.io.BufferedWriter).
|
||||||
3+ args: transducing context that writes transformed values to the specified output. The output is
|
3+ args: transducing context that writes transformed values to the specified output. The output is
|
||||||
coerced to a Writer by passing out and opts to clojure.java.io/writer. The output is automatically closed.
|
coerced to a BufferedWriter by passing out and opts to clojure.java.io/writer. The output is automatically closed.
|
||||||
Returns the writer."
|
Returns the writer."
|
||||||
([w] w)
|
([w] w)
|
||||||
([^java.io.Writer w line]
|
([^BufferedWriter w line]
|
||||||
(doto w
|
(doto w
|
||||||
(.write (str line))
|
(.write (str line))
|
||||||
(.newLine)))
|
(.newLine)))
|
||||||
([out xform coll & opts]
|
([out xform coll & opts]
|
||||||
(with-open [w (apply io/writer out opts)]
|
(with-open [^Writer w (apply io/writer out opts)]
|
||||||
(transduce xform lines-out w coll))))
|
(transduce xform lines-out w coll))))
|
||||||
|
|
||||||
(defn edn-in
|
(defn edn-in
|
||||||
|
|
@ -56,11 +61,11 @@
|
||||||
edn/read"
|
edn/read"
|
||||||
[in & {:as opts}]
|
[in & {:as opts}]
|
||||||
(let [no-init (Object.)]
|
(let [no-init (Object.)]
|
||||||
(reify clojure.lang.IReduce
|
(reify IReduce
|
||||||
(reduce [self f] (.reduce self f no-init))
|
(reduce [self f] (.reduce self f no-init))
|
||||||
(reduce [self f init]
|
(reduce [self f init]
|
||||||
(with-open [rdr (apply io/reader in (mapcat seq (keep-opts opts ::io/opts)))]
|
(with-open [^Reader rdr (apply io/reader in (mapcat seq (keep-opts opts ::io/opts)))]
|
||||||
(let [rdr (cond-> rdr (not (instance? java.io.PushbackReader rdr)) java.io.PushbackReader.)
|
(let [^BufferedReader rdr (cond-> rdr (not (instance? PushbackReader rdr)) PushbackReader.)
|
||||||
opts (assoc (keep-opts opts ::edn/opts) :eof no-init)
|
opts (assoc (keep-opts opts ::edn/opts) :eof no-init)
|
||||||
init (if (identical? init no-init)
|
init (if (identical? init no-init)
|
||||||
(let [form (edn/read opts rdr)]
|
(let [form (edn/read opts rdr)]
|
||||||
|
|
@ -83,7 +88,7 @@
|
||||||
coerced to a Writer by passing out and opts to clojure.java.io/writer. The output is automatically closed.
|
coerced to a Writer by passing out and opts to clojure.java.io/writer. The output is automatically closed.
|
||||||
Returns the writer."
|
Returns the writer."
|
||||||
([w] w)
|
([w] w)
|
||||||
([^java.io.Writer w x]
|
([^Writer w x]
|
||||||
(binding [*out* w
|
(binding [*out* w
|
||||||
*print-length* nil
|
*print-length* nil
|
||||||
*print-level* nil
|
*print-level* nil
|
||||||
|
|
@ -93,7 +98,7 @@
|
||||||
(prn x)
|
(prn x)
|
||||||
w))
|
w))
|
||||||
([out xform coll & opts]
|
([out xform coll & opts]
|
||||||
(with-open [w (apply io/writer out opts)]
|
(with-open [^Writer w (apply io/writer out opts)]
|
||||||
(transduce xform edn-out w coll))))
|
(transduce xform edn-out w coll))))
|
||||||
|
|
||||||
(defn- stream-spec [x]
|
(defn- stream-spec [x]
|
||||||
|
|
@ -108,32 +113,32 @@
|
||||||
* :dir, the current dir (defaults to clojure.java.shell/*sh-dir* or JVM current dir),
|
* :dir, the current dir (defaults to clojure.java.shell/*sh-dir* or JVM current dir),
|
||||||
* :in and :out which are maps with keys :mode (:lines (default), :text or :bytes) and :enc (defaults to \"UTF-8\");
|
* :in and :out which are maps with keys :mode (:lines (default), :text or :bytes) and :enc (defaults to \"UTF-8\");
|
||||||
encoding applies only for modes :lines or :text; shorthands exist: a single keyword is equivalent to {:mode k :enc \"UTF-8\"},
|
encoding applies only for modes :lines or :text; shorthands exist: a single keyword is equivalent to {:mode k :enc \"UTF-8\"},
|
||||||
a single string is equivelent to {:mode :lines, :enc s}.
|
a single string is equivalent to {:mode :lines, :enc s}.
|
||||||
In :bytes mode, values are bytes array.
|
In :bytes mode, values are bytes array.
|
||||||
In :lines mode, values are strings representing lines without line delimiters.
|
In :lines mode, values are strings representing lines without line delimiters.
|
||||||
In :text mode, values are strings."
|
In :text mode, values are strings."
|
||||||
{:arglists '([cmd arg1 ... argN & opts])}
|
{:arglists '([cmd arg1 ... argN & opts])}
|
||||||
[& args]
|
[& args]
|
||||||
(reify
|
(reify
|
||||||
clojure.lang.IReduce
|
IReduce
|
||||||
(reduce [self rf]
|
(reduce [self rf]
|
||||||
(reduce rf (eduction self nil))) ; quick way to handle no init
|
(reduce rf (eduction self nil))) ; quick way to handle no init
|
||||||
(reduce [self rf init]
|
(reduce [self rf init]
|
||||||
(let [xf (self rf)]
|
(let [xf (self rf)]
|
||||||
(xf init)))
|
(xf init)))
|
||||||
clojure.lang.Fn
|
Fn
|
||||||
clojure.lang.IFn
|
IFn
|
||||||
(invoke [_ rf]
|
(invoke [_ rf]
|
||||||
(let [[cmd [& {:as opts :keys [env in out dir] :or {dir sh/*sh-dir*}}]] (split-with string? args)
|
(let [[cmd [& {:as opts :keys [env in out dir] :or {dir sh/*sh-dir*}}]] (split-with string? args)
|
||||||
env (into (or sh/*sh-env* {}) env)
|
env (into (or sh/*sh-env* {}) env)
|
||||||
env (into {} (for [[k v] env] [(name k) (str v)]))
|
env (into {} (for [[k v] env] [(name k) (str v)]))
|
||||||
proc (-> ^java.util.List (map str cmd) ProcessBuilder.
|
proc (-> ^List (map str cmd) ProcessBuilder.
|
||||||
(.redirectError java.lang.ProcessBuilder$Redirect/INHERIT)
|
(.redirectError ProcessBuilder$Redirect/INHERIT)
|
||||||
(doto (-> .environment (.putAll env)))
|
(doto (-> .environment (.putAll env)))
|
||||||
(.directory (io/as-file dir))
|
(.directory (io/as-file dir))
|
||||||
.start)
|
.start)
|
||||||
EOS (Object.)
|
EOS (Object.)
|
||||||
q (java.util.concurrent.ArrayBlockingQueue. 16)
|
q (ArrayBlockingQueue. 16)
|
||||||
drain (fn [acc]
|
drain (fn [acc]
|
||||||
(loop [acc acc]
|
(loop [acc acc]
|
||||||
(if-some [x (.poll q)]
|
(if-some [x (.poll q)]
|
||||||
|
|
@ -146,41 +151,41 @@
|
||||||
acc)))
|
acc)))
|
||||||
in (stream-spec in)
|
in (stream-spec in)
|
||||||
out (stream-spec out)
|
out (stream-spec out)
|
||||||
stdin (cond-> (.getOutputStream proc) (#{:lines :text} (:mode in)) (-> (java.io.OutputStreamWriter. (:enc in)) java.io.BufferedWriter.))
|
^Closeable stdin (cond-> (.getOutputStream proc) (#{:lines :text} (:mode in)) (-> (OutputStreamWriter. ^String (:enc in)) BufferedWriter.))
|
||||||
stdout (cond-> (.getInputStream proc) (#{:lines :text} (:mode out)) (-> (java.io.InputStreamReader. (:enc out)) java.io.BufferedReader.))
|
stdout (cond-> (.getInputStream proc) (#{:lines :text} (:mode out)) (-> (InputStreamReader. ^String (:enc out)) BufferedReader.))
|
||||||
write!
|
write!
|
||||||
(case (:mode in)
|
(case (:mode in)
|
||||||
:lines
|
:lines
|
||||||
(fn [x]
|
(fn [x]
|
||||||
(doto ^java.io.BufferedWriter stdin
|
(doto ^BufferedWriter stdin
|
||||||
(.write (str x))
|
(.write (str x))
|
||||||
.newLine))
|
.newLine))
|
||||||
:text
|
:text
|
||||||
(fn [x]
|
(fn [x]
|
||||||
(.write ^java.io.BufferedWriter stdin (str x)))
|
(.write ^BufferedWriter stdin (str x)))
|
||||||
:bytes
|
:bytes
|
||||||
(fn [^bytes x]
|
(fn [^bytes x]
|
||||||
(.write ^java.io.OutputStream stdin x)))]
|
(.write ^OutputStream stdin x)))]
|
||||||
(-> (case (:mode out)
|
(-> (case (:mode out)
|
||||||
:lines
|
:lines
|
||||||
#(loop []
|
#(loop []
|
||||||
(if-some [s (.readLine ^java.io.BufferedReader stdout)]
|
(if-some [s (.readLine ^BufferedReader stdout)]
|
||||||
(do (.put q s) (recur))
|
(do (.put q s) (recur))
|
||||||
(.put q EOS)))
|
(.put q EOS)))
|
||||||
:text
|
:text
|
||||||
#(let [buf (char-array 1024)]
|
#(let [buf (char-array 1024)]
|
||||||
(loop []
|
(loop []
|
||||||
(let [n (.read ^java.io.BufferedReader stdout buf)]
|
(let [n (.read ^BufferedReader stdout buf)]
|
||||||
(if (neg? n)
|
(if (neg? n)
|
||||||
(.put q EOS)
|
(.put q EOS)
|
||||||
(do (.put q (String. buf 0 n)) (recur))))))
|
(do (.put q (String. buf 0 n)) (recur))))))
|
||||||
:bytes
|
:bytes
|
||||||
#(let [buf (byte-array 1024)]
|
#(let [buf (byte-array 1024)]
|
||||||
(loop []
|
(loop []
|
||||||
(let [n (.read ^java.io.InputStream stdout buf)]
|
(let [n (.read ^InputStream stdout buf)]
|
||||||
(if (neg? n)
|
(if (neg? n)
|
||||||
(.put q EOS)
|
(.put q EOS)
|
||||||
(do (.put q (java.util.Arrays/copyOf buf n)) (recur)))))))
|
(do (.put q (Arrays/copyOf buf n)) (recur)))))))
|
||||||
Thread. .start)
|
Thread. .start)
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
|
|
@ -197,5 +202,5 @@
|
||||||
(when-not (reduced? acc)
|
(when-not (reduced? acc)
|
||||||
(write! x))
|
(write! x))
|
||||||
acc
|
acc
|
||||||
(catch java.io.IOException e
|
(catch IOException e
|
||||||
(ensure-reduced acc))))))))))
|
(ensure-reduced acc))))))))))
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
(ns net.cgrand.xforms-test
|
(ns net.cgrand.xforms-test
|
||||||
(:require [clojure.test :refer [is deftest testing]]
|
(:refer-clojure :exclude [partition reductions])
|
||||||
|
(:require [clojure.test :refer [are is deftest testing]]
|
||||||
[net.cgrand.xforms :as x]))
|
[net.cgrand.xforms :as x]))
|
||||||
|
|
||||||
(defn trial
|
(defn trial
|
||||||
|
|
@ -94,11 +95,12 @@
|
||||||
(is (= {0 :ok 2 :ok 4 :ok 6 :ok 8 :ok} (x/without (zipmap (range 10) (repeat :ok)) (filter odd?) (range 20))))
|
(is (= {0 :ok 2 :ok 4 :ok 6 :ok 8 :ok} (x/without (zipmap (range 10) (repeat :ok)) (filter odd?) (range 20))))
|
||||||
(is (= #{0 2 4 6 8 } (x/without (set (range 10)) (filter odd?) (range 20)))))
|
(is (= #{0 2 4 6 8 } (x/without (set (range 10)) (filter odd?) (range 20)))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:bb nil ;; babashka doesn't currently support calling iterator on range type
|
||||||
|
:clj
|
||||||
(deftest iterator
|
(deftest iterator
|
||||||
(is (true? (.hasNext (x/iterator x/count (.iterator (range 5))))))
|
(is (true? (.hasNext (x/iterator x/count (.iterator ^java.lang.Iterable (range 5))))))
|
||||||
(is (is (= [5] (iterator-seq (x/iterator x/count (.iterator (range 5)))))))
|
(is (is (= [5] (iterator-seq (x/iterator x/count (.iterator ^java.lang.Iterable (range 5)))))))
|
||||||
(is (= [[0 1] [1 2] [2 3] [3 4] [4]] (iterator-seq (x/iterator (x/partition 2 1 nil) (.iterator (range 5)))))))
|
(is (= [[0 1] [1 2] [2 3] [3 4] [4]] (iterator-seq (x/iterator (x/partition 2 1 nil) (.iterator ^java.lang.Iterable (range 5)))))))
|
||||||
|
|
||||||
(deftest window-by-time
|
(deftest window-by-time
|
||||||
(is (= (into
|
(is (= (into
|
||||||
|
|
@ -139,4 +141,17 @@
|
||||||
(is (= (range 100) (x/into [] (x/sort) (shuffle (range 100)))))
|
(is (= (range 100) (x/into [] (x/sort) (shuffle (range 100)))))
|
||||||
(is (= (reverse (range 100)) (x/into [] (x/sort >) (shuffle (range 100)))))
|
(is (= (reverse (range 100)) (x/into [] (x/sort >) (shuffle (range 100)))))
|
||||||
(is (= (sort-by str (range 100)) (x/into [] (x/sort-by str) (shuffle (range 100)))))
|
(is (= (sort-by str (range 100)) (x/into [] (x/sort-by str) (shuffle (range 100)))))
|
||||||
(is (= (sort-by str (comp - compare) (range 100)) (x/into [] (x/sort-by str (comp - compare)) (shuffle (range 100))))))
|
(is (= (sort-by str (comp - compare) (range 100)) (x/into [] (x/sort-by str (comp - compare)) (shuffle (range 100))))))
|
||||||
|
|
||||||
|
(deftest destructuring-pair?
|
||||||
|
(let [destructuring-pair? #'x/destructuring-pair?]
|
||||||
|
(are [candidate expected]
|
||||||
|
(= expected (destructuring-pair? candidate))
|
||||||
|
'[a b] true
|
||||||
|
'[a b c] false
|
||||||
|
'[& foo] false
|
||||||
|
'[:as foo] false
|
||||||
|
1 false
|
||||||
|
'(a b) false
|
||||||
|
'{foo bar} false
|
||||||
|
'{foo :bar} false)))
|
||||||
|
|
|
||||||
1
tests.edn
Normal file
1
tests.edn
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#kaocha/v1 {}
|
||||||
Loading…
Reference in a new issue