Compare commits
No commits in common. "master" and "v0.19.3" have entirely different histories.
9 changed files with 253 additions and 406 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -8,9 +8,6 @@ pom.xml.asc
|
||||||
*.class
|
*.class
|
||||||
/lib/
|
/lib/
|
||||||
/classes/
|
/classes/
|
||||||
/bin/
|
|
||||||
/node_modules/
|
|
||||||
/.lumo_cache/
|
|
||||||
/target/
|
/target/
|
||||||
/checkouts/
|
/checkouts/
|
||||||
.lein-deps-sum
|
.lein-deps-sum
|
||||||
|
|
@ -20,6 +17,5 @@ pom.xml.asc
|
||||||
.nrepl-port
|
.nrepl-port
|
||||||
.cpcache/
|
.cpcache/
|
||||||
.clj-kondo/*/
|
.clj-kondo/*/
|
||||||
/cljs-test-runner-out/
|
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/clojure
|
# End of https://www.toptal.com/developers/gitignore/api/clojure
|
||||||
|
|
|
||||||
27
README.md
27
README.md
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
More transducers and reducing functions for Clojure(script)!
|
More transducers and reducing functions for Clojure(script)!
|
||||||
|
|
||||||
|
[](https://travis-ci.org/cgrand/xforms)
|
||||||
|
|
||||||
*Transducers* can be classified in three groups: regular ones, higher-order ones
|
*Transducers* can be classified in three groups: regular ones, higher-order ones
|
||||||
(which accept other transducers as arguments) and aggregators (transducers which emit only 1 item out no matter how many went in).
|
(which accept other transducers as arguments) and aggregators (transducers which emit only 1 item out no matter how many went in).
|
||||||
Aggregators generally only make sense in the context of a higher-order transducer.
|
Aggregators generally only make sense in the context of a higher-order transducer.
|
||||||
|
|
@ -35,7 +37,17 @@ In `net.cgrand.xforms.io`:
|
||||||
|
|
||||||
## Add as a dependency
|
## Add as a dependency
|
||||||
|
|
||||||
For specific coordinates see the [Releases](https://github.com/cgrand/xforms/releases) page.
|
### tools.deps
|
||||||
|
|
||||||
|
See the [Releases](/releases) page for coordinates.
|
||||||
|
|
||||||
|
### Leiningen
|
||||||
|
|
||||||
|
**Note that as of the writing of this, 0.19.3 (and perhaps later versions) are not yet published as jars**
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[net.cgrand/xforms "0.19.2"]
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
@ -228,19 +240,6 @@ Evaluation count : 24 in 6 samples of 4 calls.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### 0.19.6
|
|
||||||
|
|
||||||
* Fix regression in 0.19.5 #54
|
|
||||||
|
|
||||||
### 0.19.5
|
|
||||||
|
|
||||||
* Support ClojureDart
|
|
||||||
|
|
||||||
### 0.19.4
|
|
||||||
|
|
||||||
* Fix ClojureScript compilation broken in `0.19.3` #49
|
|
||||||
* Fix `x/sort` and `x/sort-by` for ClojureScript #40
|
|
||||||
|
|
||||||
### 0.19.3
|
### 0.19.3
|
||||||
|
|
||||||
* Add `deps.edn` to enable usage as a [git library](https://clojure.org/guides/deps_and_cli#_using_git_libraries)
|
* Add `deps.edn` to enable usage as a [git library](https://clojure.org/guides/deps_and_cli#_using_git_libraries)
|
||||||
|
|
|
||||||
33
bb.edn
33
bb.edn
|
|
@ -2,48 +2,29 @@
|
||||||
:paths ["src" "test"]
|
:paths ["src" "test"]
|
||||||
|
|
||||||
:tasks
|
:tasks
|
||||||
{:requires ([clojure.string :as str])
|
{:init
|
||||||
|
|
||||||
:init
|
|
||||||
(do
|
(do
|
||||||
(defn kaocha [alias args]
|
(defn kaocha [alias args]
|
||||||
(apply shell "bin/kaocha" alias args))
|
(apply shell "bin/kaocha" alias args)))
|
||||||
|
|
||||||
(defn test-cljs [alias args]
|
test-9
|
||||||
(apply clojure (str/join ["-M:test:cljs-test-runner" alias]) args)))
|
|
||||||
|
|
||||||
test-clj-9
|
|
||||||
{:task (kaocha :clj-1-9 *command-line-args*)}
|
{:task (kaocha :clj-1-9 *command-line-args*)}
|
||||||
|
|
||||||
test-clj-10
|
test-10
|
||||||
{:task (kaocha :clj-1-10 *command-line-args*)}
|
{:task (kaocha :clj-1-10 *command-line-args*)}
|
||||||
|
|
||||||
test-clj-11
|
test-11
|
||||||
{:task (kaocha :clj-1-11 *command-line-args*)}
|
{:task (kaocha :clj-1-11 *command-line-args*)}
|
||||||
|
|
||||||
test-clj
|
test-clj
|
||||||
{:depends [test-clj-9 test-clj-10 test-clj-11]}
|
{:task (doseq [alias [:clj-1-9 :clj-1-10 :clj-1-11]]
|
||||||
|
(kaocha alias *command-line-args*))}
|
||||||
test-cljs-9
|
|
||||||
{:task (test-cljs :clj-1-9 *command-line-args*)}
|
|
||||||
|
|
||||||
test-cljs-10
|
|
||||||
{:task (test-cljs :clj-1-10 *command-line-args*)}
|
|
||||||
|
|
||||||
test-cljs-11
|
|
||||||
{:task (test-cljs :clj-1-11 *command-line-args*)}
|
|
||||||
|
|
||||||
test-cljs
|
|
||||||
{:depends [#_test-cljs-9 test-cljs-10 test-cljs-11]}
|
|
||||||
|
|
||||||
test-bb
|
test-bb
|
||||||
{:requires ([clojure.test :as t]
|
{:requires ([clojure.test :as t]
|
||||||
[net.cgrand.xforms-test])
|
[net.cgrand.xforms-test])
|
||||||
:task (t/run-tests 'net.cgrand.xforms-test)}
|
:task (t/run-tests 'net.cgrand.xforms-test)}
|
||||||
|
|
||||||
test-all
|
|
||||||
{:depends [test-bb test-clj test-cljs]}
|
|
||||||
|
|
||||||
perf-bb
|
perf-bb
|
||||||
{:requires ([net.cgrand.xforms :as x])
|
{:requires ([net.cgrand.xforms :as x])
|
||||||
:task
|
:task
|
||||||
|
|
|
||||||
46
build.clj
46
build.clj
|
|
@ -1,46 +0,0 @@
|
||||||
(ns build
|
|
||||||
(:require [clojure.tools.build.api :as b]
|
|
||||||
[clojure.java.shell :as sh]))
|
|
||||||
|
|
||||||
(def lib 'net.cgrand/xforms)
|
|
||||||
(def version "0.19.6" #_(format "0.0.%s" (b/git-count-revs nil)))
|
|
||||||
(def class-dir "target/classes")
|
|
||||||
(def basis (b/create-basis {:project "deps.edn"}))
|
|
||||||
(def jar-file (format "target/%s-%s.jar" (name lib) version))
|
|
||||||
(def scm {:connection "scm:git:git://github.com/cgrand/xforms.git"
|
|
||||||
:developerConnection "scm:git:git://github.com/cgrand/xforms.git"
|
|
||||||
:url "https://github.com/cgrand/xforms"})
|
|
||||||
(def extra-pom-data
|
|
||||||
[[:licenses
|
|
||||||
[:license
|
|
||||||
[:name "Eclipse Public License 1.0"]
|
|
||||||
[:url "https://opensource.org/license/epl-1-0/"]
|
|
||||||
[:distribution "repo"]]
|
|
||||||
[:license
|
|
||||||
[:name "Eclipse Public License 2.0"]
|
|
||||||
[:url "https://opensource.org/license/epl-2-0/"]
|
|
||||||
[:distribution "repo"]]]])
|
|
||||||
|
|
||||||
(defn clean [_]
|
|
||||||
(b/delete {:path "target"}))
|
|
||||||
|
|
||||||
(defn jar [_]
|
|
||||||
(b/write-pom {:class-dir class-dir
|
|
||||||
:lib lib
|
|
||||||
:version version
|
|
||||||
:basis basis
|
|
||||||
:src-dirs ["src"]
|
|
||||||
:scm (assoc scm :tag (str "v" version))
|
|
||||||
:pom-data extra-pom-data})
|
|
||||||
(b/copy-dir {:src-dirs ["src" "resources"]
|
|
||||||
:target-dir class-dir})
|
|
||||||
(b/jar {:class-dir class-dir
|
|
||||||
:jar-file jar-file}))
|
|
||||||
|
|
||||||
(defn clojars [_]
|
|
||||||
(sh/sh
|
|
||||||
"mvn" "deploy:deploy-file" (str "-Dfile=" jar-file)
|
|
||||||
;target/classes/META-INF/maven/net.cgrand/xforms/pom.xml
|
|
||||||
(format "-DpomFile=%s/META-INF/maven/%s/%s/pom.xml"
|
|
||||||
class-dir (namespace lib) (name lib))
|
|
||||||
"-DrepositoryId=clojars" "-Durl=https://clojars.org/repo/"))
|
|
||||||
23
deps.edn
23
deps.edn
|
|
@ -1,16 +1,10 @@
|
||||||
{:deps {net.cgrand/macrovich {:mvn/version "0.2.2"}}
|
{:deps {net.cgrand/macrovich {:mvn/version "0.2.1"}}
|
||||||
:paths ["src"]
|
:paths ["src"]
|
||||||
|
|
||||||
:aliases
|
:aliases
|
||||||
{:dev
|
{:dev
|
||||||
{:extra-paths ["dev"]}
|
{:extra-paths ["dev"]}
|
||||||
|
|
||||||
:cljd
|
|
||||||
{:extra-deps
|
|
||||||
{tensegritics/clojuredart
|
|
||||||
{:git/url "https://github.com/tensegritics/ClojureDart.git"
|
|
||||||
:sha "ae1b485e84ccc35b122f776dfc7cc62198274701"}}}
|
|
||||||
|
|
||||||
:clj-1-9
|
:clj-1-9
|
||||||
{:extra-deps
|
{:extra-deps
|
||||||
{org.clojure/clojure {:mvn/version "1.9.0"}
|
{org.clojure/clojure {:mvn/version "1.9.0"}
|
||||||
|
|
@ -30,16 +24,5 @@
|
||||||
{:extra-paths ["test"]}
|
{:extra-paths ["test"]}
|
||||||
|
|
||||||
:kaocha
|
:kaocha
|
||||||
{:extra-paths ["test"]
|
{:extra-deps {lambdaisland/kaocha {:mvn/version "1.69.1069"}}
|
||||||
:extra-deps {lambdaisland/kaocha {:mvn/version "1.69.1069"}}
|
:main-opts ["-m" "kaocha.runner"]}}}
|
||||||
:main-opts ["-m" "kaocha.runner"]}
|
|
||||||
|
|
||||||
:cljs-test-runner
|
|
||||||
{:extra-paths ["test"]
|
|
||||||
:extra-deps {olical/cljs-test-runner {:mvn/version "3.8.0"}}
|
|
||||||
:main-opts ["-m" "cljs-test-runner.main"]}
|
|
||||||
|
|
||||||
:build
|
|
||||||
{:paths ["."]
|
|
||||||
:deps {io.github.clojure/tools.build {:git/tag "v0.9.6" :git/sha "8e78bcc"}}
|
|
||||||
:ns-default build}}}
|
|
||||||
|
|
|
||||||
14
project.clj
Normal file
14
project.clj
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
(defproject net.cgrand/xforms "0.19.3"
|
||||||
|
:description "Extra transducers for Clojure"
|
||||||
|
:url "https://github.com/cgrand/xforms"
|
||||||
|
:license {:name "Eclipse Public License"
|
||||||
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||||
|
|
||||||
|
:plugins [[lein-tools-deps "0.4.5"]]
|
||||||
|
: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"]]}})
|
||||||
|
|
@ -4,31 +4,18 @@
|
||||||
#?(:cljs (:require-macros
|
#?(:cljs (:require-macros
|
||||||
[net.cgrand.macrovich :as macros]
|
[net.cgrand.macrovich :as macros]
|
||||||
[net.cgrand.xforms :refer [for kvrf let-complete]])
|
[net.cgrand.xforms :refer [for kvrf let-complete]])
|
||||||
:default (: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 #?@(:bb [] :cljd/clj-host [] :clj [satisfies?])])
|
sort sort-by time satisfies?])
|
||||||
(:require [#?(:cljd cljd.core :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]
|
||||||
#?@(:cljd [["dart:collection" :as dart:coll]] :clj [[clojure.core.protocols]] :cljs []))
|
#?(:clj [clojure.core.protocols]))
|
||||||
#?(:cljd/clj-host
|
|
||||||
; customize the clj/jvm ns used for macroexpansion
|
|
||||||
(:host-ns (:require [clojure.core :as core]
|
|
||||||
[net.cgrand.macrovich :as macros])))
|
|
||||||
#?(:cljs (:import [goog.structs Queue])))
|
#?(:cljs (:import [goog.structs Queue])))
|
||||||
|
|
||||||
(defn- ^:macro-support pair? [x] (and (vector? x) (= 2 (core/count x))))
|
|
||||||
(def ^:macro-support destructuring-pair?
|
|
||||||
(let [kw-or-& #(or (keyword? %) (= '& %))]
|
|
||||||
(fn [x]
|
|
||||||
(and (pair? x)
|
|
||||||
(not (kw-or-& (first x)))))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(macros/deftime
|
(macros/deftime
|
||||||
|
|
||||||
(defn- ^:macro-support no-user-meta? [x]
|
(defn- no-user-meta? [x]
|
||||||
(= {} (dissoc (or (meta x) {}) :file :line :column :end-line :end-column)))
|
(= {} (dissoc (or (meta x) {}) :file :line :column :end-line :end-column)))
|
||||||
|
|
||||||
(defmacro unreduced->
|
(defmacro unreduced->
|
||||||
|
|
@ -41,6 +28,12 @@
|
||||||
x#
|
x#
|
||||||
(unreduced-> (-> x# ~expr) ~@exprs)))))
|
(unreduced-> (-> x# ~expr) ~@exprs)))))
|
||||||
|
|
||||||
|
(defn- pair? [x] (and (vector? x) (= 2 (core/count x))))
|
||||||
|
(let [kw-or-& #(or (keyword? %) (= '& %))]
|
||||||
|
(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.
|
||||||
When the first expression is not % (or _) returns an eduction."
|
When the first expression is not % (or _) returns an eduction."
|
||||||
|
|
@ -89,7 +82,7 @@
|
||||||
([~acc] (~rf ~acc))
|
([~acc] (~rf ~acc))
|
||||||
([~acc ~binding] ~body)))))))
|
([~acc ~binding] ~body)))))))
|
||||||
|
|
||||||
(defn- ^:macro-support arity [[arglist & body :as fn-body]]
|
(defn- arity [[arglist & body :as fn-body]]
|
||||||
(let [[fixargs varargs] (split-with (complement #{'&}) arglist)]
|
(let [[fixargs varargs] (split-with (complement #{'&}) arglist)]
|
||||||
(if (seq varargs) (zipmap (range (core/count fixargs) 4) (repeat fn-body)))
|
(if (seq varargs) (zipmap (range (core/count fixargs) 4) (repeat fn-body)))
|
||||||
{(core/count fixargs) fn-body}))
|
{(core/count fixargs) fn-body}))
|
||||||
|
|
@ -105,27 +98,20 @@
|
||||||
(if (destructuring-pair? arg)
|
(if (destructuring-pair? arg)
|
||||||
(let [[karg varg] arg]
|
(let [[karg varg] arg]
|
||||||
`([~acc ~karg ~varg] ~@body))
|
`([~acc ~karg ~varg] ~@body))
|
||||||
(let [k (gensym "k__")
|
`([~acc k# v#] (let [~arg (macros/case :clj (clojure.lang.MapEntry. k# v#) :cljs [k# v#])] ~@body)))))
|
||||||
v (gensym "v__")
|
|
||||||
arg-value (macros/case
|
|
||||||
:clj `(clojure.lang.MapEntry. ~k ~v)
|
|
||||||
:cljs [k v]
|
|
||||||
:cljd `(MapEntry ~k ~v))]
|
|
||||||
`([~acc ~k ~v] (let [~arg ~arg-value] ~@body))))))
|
|
||||||
(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
|
||||||
#?@(:bb [] ;; babashka currently only supports reify with one Java interface at a time
|
#?@(:bb [] ;; babashka currently only supports reify with one Java interface at a time
|
||||||
:default [~@(macros/case :cljd '[cljd.core/Fn] :clj '[clojure.lang.Fn])])
|
: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 :cljd 'cljd.core/IFn)
|
~(macros/case :cljs `core/IFn :clj 'clojure.lang.IFn)
|
||||||
~@(core/for [[args & body] fn-bodies]
|
~@(core/for [[args & body] fn-bodies]
|
||||||
(let [nohint-args (map (fn [arg] (if (:tag (meta arg)) (gensym 'arg) arg)) args)
|
(let [nohint-args (map (fn [arg] (if (:tag (meta arg)) (gensym 'arg) arg)) args)
|
||||||
rebind (mapcat (fn [arg nohint]
|
rebind (mapcat (fn [arg nohint]
|
||||||
(when-not (= arg nohint) [arg nohint])) args nohint-args)]
|
(when-not (= arg nohint) [arg nohint])) args nohint-args)]
|
||||||
`(~(macros/case :cljd '-invoke :cljs `core/-invoke :clj 'invoke)
|
`(~(macros/case :cljs `core/-invoke :clj 'invoke) [~name ~@nohint-args] ~@(if (seq rebind) [`(let [~@rebind] ~@body)] body)))))))
|
||||||
[~name ~@nohint-args] ~@(if (seq rebind) [`(let [~@rebind] ~@body)] body)))))))
|
|
||||||
|
|
||||||
(defmacro ^:private let-complete [[binding volatile] & body]
|
(defmacro ^:private let-complete [[binding volatile] & body]
|
||||||
`(let [v# @~volatile]
|
`(let [v# @~volatile]
|
||||||
|
|
@ -144,8 +130,12 @@
|
||||||
|
|
||||||
;; Workaround clojure.core/satisfies? being slow in Clojure
|
;; Workaround clojure.core/satisfies? being slow in Clojure
|
||||||
;; see https://ask.clojure.org/index.php/3304/make-satisfies-as-fast-as-a-protocol-method-call
|
;; see https://ask.clojure.org/index.php/3304/make-satisfies-as-fast-as-a-protocol-method-call
|
||||||
#?(:bb nil
|
#?(:cljs
|
||||||
:cljd nil
|
(def satisfies? core/satisfies?)
|
||||||
|
|
||||||
|
:bb
|
||||||
|
(def satisfies? core/satisfies?)
|
||||||
|
|
||||||
:clj
|
:clj
|
||||||
(defn fast-satisfies?-fn
|
(defn fast-satisfies?-fn
|
||||||
"Ported from https://github.com/clj-commons/manifold/blob/37658e91f836047a630586a909a2e22debfbbfc6/src/manifold/utils.clj#L77-L89"
|
"Ported from https://github.com/clj-commons/manifold/blob/37658e91f836047a630586a909a2e22debfbbfc6/src/manifold/utils.clj#L77-L89"
|
||||||
|
|
@ -162,13 +152,10 @@
|
||||||
val)
|
val)
|
||||||
val))))))
|
val))))))
|
||||||
|
|
||||||
|
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(defn kvreducible? [coll]
|
(defn kvreducible? [coll]
|
||||||
(satisfies? IKVReduce coll))
|
(satisfies? core/IKVReduce coll))
|
||||||
|
|
||||||
:cljd
|
|
||||||
(defn kvreducible? [coll]
|
|
||||||
(satisfies? cljd.core/IKVReduce coll))
|
|
||||||
|
|
||||||
:clj
|
:clj
|
||||||
(let [satisfies-ikvreduce? #?(:bb #(satisfies? clojure.core.protocols/IKVReduce %)
|
(let [satisfies-ikvreduce? #?(:bb #(satisfies? clojure.core.protocols/IKVReduce %)
|
||||||
|
|
@ -181,7 +168,7 @@
|
||||||
|
|
||||||
|
|
||||||
(extend-protocol KvRfable
|
(extend-protocol KvRfable
|
||||||
#?(:cljd fallback :clj Object :cljs default) (some-kvrf [_] nil)
|
#?(:clj Object :cljs default) (some-kvrf [_] nil)
|
||||||
#?@(:clj [nil (some-kvrf [_] nil)]))
|
#?@(:clj [nil (some-kvrf [_] nil)]))
|
||||||
|
|
||||||
(defn ensure-kvrf [rf]
|
(defn ensure-kvrf [rf]
|
||||||
|
|
@ -215,9 +202,8 @@
|
||||||
|
|
||||||
(defn- into-rf [to]
|
(defn- into-rf [to]
|
||||||
(cond
|
(cond
|
||||||
#?(:cljd (satisfies? cljd.core/IEditableCollection to)
|
#?(:clj (instance? clojure.lang.IEditableCollection to)
|
||||||
:clj (instance? clojure.lang.IEditableCollection to)
|
:cljs (satisfies? IEditableCollection to))
|
||||||
:cljs (satisfies? IEditableCollection to))
|
|
||||||
(if (map? to)
|
(if (map? to)
|
||||||
(kvrf
|
(kvrf
|
||||||
([] (transient to))
|
([] (transient to))
|
||||||
|
|
@ -254,9 +240,8 @@
|
||||||
|
|
||||||
(defn- without-rf [from]
|
(defn- without-rf [from]
|
||||||
(cond
|
(cond
|
||||||
#?(:cljd (satisfies? cljd.core/IEditableCollection from)
|
#?(:clj (instance? clojure.lang.IEditableCollection from)
|
||||||
:clj (instance? clojure.lang.IEditableCollection from)
|
:cljs (satisfies? IEditableCollection from))
|
||||||
:cljs (satisfies? IEditableCollection from))
|
|
||||||
(if (map? from)
|
(if (map? from)
|
||||||
(fn
|
(fn
|
||||||
([] (transient from))
|
([] (transient from))
|
||||||
|
|
@ -430,36 +415,32 @@
|
||||||
(comp (apply by-key by-key-args) (into coll)))
|
(comp (apply by-key by-key-args) (into coll)))
|
||||||
|
|
||||||
(macros/replace
|
(macros/replace
|
||||||
[#?(:cljd {(java.util.ArrayDeque. n) (dart:coll/Queue)
|
[#?(:cljs {(java.util.ArrayDeque. n) (Queue.)
|
||||||
.add .add
|
|
||||||
.poll .removeFirst
|
|
||||||
.size .-length})
|
|
||||||
#?(:cljs {(java.util.ArrayDeque. n) (Queue.)
|
|
||||||
.add .enqueue
|
.add .enqueue
|
||||||
.poll .dequeue
|
.poll .dequeue
|
||||||
.size .getCount})
|
.size .getCount})
|
||||||
#?(:clj {(.getValues dq) dq})]
|
#?(:clj {(.getValues dq) dq})]
|
||||||
|
|
||||||
(defn partition
|
(defn partition
|
||||||
"Returns a partitioning transducer. Each partition is independently transformed using the xform transducer."
|
"Returns a partitioning transducer. Each partition is independently transformed using the xform transducer."
|
||||||
([n]
|
([n]
|
||||||
(partition n n (into [])))
|
(partition n n (into [])))
|
||||||
([n step-or-xform]
|
([n step-or-xform]
|
||||||
(if (fn? step-or-xform)
|
(if (fn? step-or-xform)
|
||||||
(partition n n step-or-xform)
|
(partition n n step-or-xform)
|
||||||
(partition n step-or-xform (into []))))
|
(partition n step-or-xform (into []))))
|
||||||
([#?(:cljd ^int n :default ^long n) step pad-or-xform]
|
([^long n step pad-or-xform]
|
||||||
(if (fn? pad-or-xform)
|
(if (fn? pad-or-xform)
|
||||||
(let [xform pad-or-xform]
|
(let [xform pad-or-xform]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [mxrf (multiplexable rf)
|
(let [mxrf (multiplexable rf)
|
||||||
dq (java.util.ArrayDeque. n)
|
dq (java.util.ArrayDeque. n)
|
||||||
barrier (volatile! n)
|
barrier (volatile! n)
|
||||||
xform (comp (map #(if (identical? dq %) nil %)) xform)]
|
xform (comp (map #(if (identical? dq %) nil %)) xform)]
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc] (.clear dq) (rf acc))
|
([acc] (.clear dq) (rf acc))
|
||||||
([acc x]
|
([acc x]
|
||||||
(let [b (vswap! barrier dec)]
|
(let [b (vswap! barrier dec)]
|
||||||
(when (< b n) (.add dq (if (nil? x) dq x)))
|
(when (< b n) (.add dq (if (nil? x) dq x)))
|
||||||
(if (zero? b)
|
(if (zero? b)
|
||||||
|
|
@ -469,24 +450,24 @@
|
||||||
(vswap! barrier + step)
|
(vswap! barrier + step)
|
||||||
acc)
|
acc)
|
||||||
acc)))))))
|
acc)))))))
|
||||||
(partition n step pad-or-xform (into []))))
|
(partition n step pad-or-xform (into []))))
|
||||||
([#?(:cljd ^int n :default ^long n) step pad xform]
|
([^long n step pad xform]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [mxrf (multiplexable rf)
|
(let [mxrf (multiplexable rf)
|
||||||
dq (java.util.ArrayDeque. n)
|
dq (java.util.ArrayDeque. n)
|
||||||
barrier (volatile! n)
|
barrier (volatile! n)
|
||||||
xform (comp (map #(if (identical? dq %) nil %)) xform)]
|
xform (comp (map #(if (identical? dq %) nil %)) xform)]
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc] (if (< @barrier n)
|
([acc] (if (< @barrier n)
|
||||||
(let [xform (comp cat (take n) xform)
|
(let [xform (comp cat (take n) xform)
|
||||||
; don't use mxrf for completion: we want completion and don't want reduced-wrapping
|
; don't use mxrf for completion: we want completion and don't want reduced-wrapping
|
||||||
acc (transduce xform rf acc [(.getValues dq) pad])]
|
acc (transduce xform rf acc [(.getValues dq) pad])]
|
||||||
(vreset! barrier n)
|
(vreset! barrier n)
|
||||||
(.clear dq)
|
(.clear dq)
|
||||||
acc)
|
acc)
|
||||||
(rf acc)))
|
(rf acc)))
|
||||||
([acc x]
|
([acc x]
|
||||||
(let [b (vswap! barrier dec)]
|
(let [b (vswap! barrier dec)]
|
||||||
(when (< b n) (.add dq (if (nil? x) dq x)))
|
(when (< b n) (.add dq (if (nil? x) dq x)))
|
||||||
(if (zero? b)
|
(if (zero? b)
|
||||||
|
|
@ -501,7 +482,7 @@
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let )))
|
(let )))
|
||||||
|
|
||||||
(defn take-last [#?(:cljd ^int n :default ^long n)]
|
(defn take-last [^long n]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [dq (java.util.ArrayDeque. n)]
|
(let [dq (java.util.ArrayDeque. n)]
|
||||||
(fn
|
(fn
|
||||||
|
|
@ -514,7 +495,7 @@
|
||||||
|
|
||||||
(defn drop-last
|
(defn drop-last
|
||||||
([] (drop-last 1))
|
([] (drop-last 1))
|
||||||
([#?(:cljd ^int n :default ^long n)]
|
([^long n]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [dq (java.util.ArrayDeque. n)
|
(let [dq (java.util.ArrayDeque. n)
|
||||||
xform (map #(if (identical? dq %) nil %))
|
xform (map #(if (identical? dq %) nil %))
|
||||||
|
|
@ -530,41 +511,21 @@
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#?(:cljs
|
|
||||||
(defn ^:private fn->comparator
|
|
||||||
"Given a fn that might be boolean valued or a comparator,
|
|
||||||
return a fn that is a comparator.
|
|
||||||
|
|
||||||
Copied from cljs.core: https://github.com/clojure/clojurescript/blob/95c5cf384a128503b072b7b1916af1a1d5c8871c/src/main/cljs/cljs/core.cljs#L2459-L2471"
|
|
||||||
[f]
|
|
||||||
(if (= f compare)
|
|
||||||
compare
|
|
||||||
(fn [x y]
|
|
||||||
(let [r (f x y)]
|
|
||||||
(if (number? r)
|
|
||||||
r
|
|
||||||
(if r
|
|
||||||
-1
|
|
||||||
(if (f y x) 1 0))))))))
|
|
||||||
|
|
||||||
(defn sort
|
(defn sort
|
||||||
([] (sort compare))
|
([] (sort compare))
|
||||||
([cmp]
|
([cmp]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [buf #?(:cljd #dart [] :clj (java.util.ArrayList.) :cljs #js [])]
|
(let [buf #?(:clj (java.util.ArrayList.) :cljs #js [])]
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc] (rf (core/reduce rf acc (doto buf #?(:cljd (.sort (dart-comparator cmp))
|
([acc] (rf (core/reduce rf acc (doto buf #?(:clj (java.util.Collections/sort cmp) :cljs (.sort cmp))))))
|
||||||
:clj (java.util.Collections/sort cmp)
|
([acc x] (#?(:clj .add :cljs .push) buf x) acc))))))
|
||||||
:cljs (.sort (fn->comparator cmp)))))))
|
|
||||||
([acc x] (#?(:cljd .add :clj .add :cljs .push) buf x) acc))))))
|
|
||||||
|
|
||||||
(defn sort-by
|
(defn sort-by
|
||||||
([kfn] (sort-by kfn compare))
|
([kfn] (sort-by kfn compare))
|
||||||
([kfn cmp]
|
([kfn cmp]
|
||||||
(sort (fn [a b]
|
(sort (fn [a b]
|
||||||
#?(:cljd (cmp (kfn a) (kfn b))
|
#?(:clj (.compare ^java.util.Comparator cmp (kfn a) (kfn b))
|
||||||
:clj (.compare ^java.util.Comparator cmp (kfn a) (kfn b))
|
|
||||||
:cljs (cmp (kfn a) (kfn b)))))))
|
:cljs (cmp (kfn a) (kfn b)))))))
|
||||||
|
|
||||||
(defn reductions
|
(defn reductions
|
||||||
|
|
@ -630,8 +591,7 @@
|
||||||
(vreset! vi (let [i (inc i)] (if (= n i) 0 i)))
|
(vreset! vi (let [i (inc i)] (if (= n i) 0 i)))
|
||||||
(rf acc (f (vreset! vwacc (f (invf wacc x') x))))))))))))
|
(rf acc (f (vreset! vwacc (f (invf wacc x') x))))))))))))
|
||||||
|
|
||||||
#?(:cljd nil
|
#?(:clj
|
||||||
:clj
|
|
||||||
(defn iterator
|
(defn iterator
|
||||||
"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),
|
||||||
|
|
@ -662,8 +622,7 @@
|
||||||
(if (identical? NULL x) nil x))
|
(if (identical? NULL x) nil x))
|
||||||
(throw (java.util.NoSuchElementException.))))))))
|
(throw (java.util.NoSuchElementException.))))))))
|
||||||
|
|
||||||
#?(:cljd nil
|
#?(:clj
|
||||||
:clj
|
|
||||||
(defn window-by-time
|
(defn window-by-time
|
||||||
"ALPHA
|
"ALPHA
|
||||||
Returns a transducer which computes a windowed accumulator over chronologically sorted items.
|
Returns a transducer which computes a windowed accumulator over chronologically sorted items.
|
||||||
|
|
@ -729,11 +688,11 @@
|
||||||
"Count the number of items. Either used directly as a transducer or invoked with two args
|
"Count the number of items. Either used directly as a transducer or invoked with two args
|
||||||
as a transducing context."
|
as a transducing context."
|
||||||
([rf]
|
([rf]
|
||||||
(let [n #?(:cljd (volatile! 0) :clj (java.util.concurrent.atomic.AtomicLong.) :cljs (volatile! 0))]
|
(let [n #?(:clj (java.util.concurrent.atomic.AtomicLong.) :cljs (atom 0))]
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc] (rf (unreduced (rf acc #?(:cljd @n :clj (.get n) :cljs @n)))))
|
([acc] (rf (unreduced (rf acc #?(:clj (.get n) :cljs @n)))))
|
||||||
([acc _] #?(:cljd (vswap! n inc) :clj (.incrementAndGet n) :cljs (vswap! n inc)) acc))))
|
([acc _] #?(:clj (.incrementAndGet n) :cljs (swap! n inc)) acc))))
|
||||||
([xform coll]
|
([xform coll]
|
||||||
(transduce (comp xform count) rf/last coll)))
|
(transduce (comp xform count) rf/last coll)))
|
||||||
|
|
||||||
|
|
@ -827,45 +786,43 @@
|
||||||
(.addAndGet at (- (System/nanoTime) t)) (swap! at + (- (system-time) t))
|
(.addAndGet at (- (System/nanoTime) t)) (swap! at + (- (system-time) t))
|
||||||
.size .getCount})]
|
.size .getCount})]
|
||||||
|
|
||||||
#?(:cljd nil
|
(defn time
|
||||||
:default
|
"Measures the time spent in this transformation and prints the measured time.
|
||||||
(defn time
|
|
||||||
"Measures the time spent in this transformation and prints the measured time.
|
|
||||||
tag-or-f may be either a function of 1 argument (measured time in ms) in which case
|
tag-or-f may be either a function of 1 argument (measured time in ms) in which case
|
||||||
this function will be called instead of printing, or tag-or-f will be print before the measured time."
|
this function will be called instead of printing, or tag-or-f will be print before the measured time."
|
||||||
([xform] (time "Elapsed time" xform))
|
([xform] (time "Elapsed time" xform))
|
||||||
([tag-or-f xform]
|
([tag-or-f xform]
|
||||||
(let [pt (if (fn? tag-or-f)
|
(let [pt (if (fn? tag-or-f)
|
||||||
tag-or-f
|
tag-or-f
|
||||||
#(println (core/str tag-or-f ": " % " msecs")))]
|
#(println (core/str tag-or-f ": " % " msecs")))]
|
||||||
(fn [rf]
|
(fn [rf]
|
||||||
(let [at (java.util.concurrent.atomic.AtomicLong.)
|
(let [at (java.util.concurrent.atomic.AtomicLong.)
|
||||||
rf
|
rf
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc] (let [t (System/nanoTime)
|
([acc] (let [t (System/nanoTime)
|
||||||
r (rf acc)]
|
r (rf acc)]
|
||||||
(.addAndGet at (- t (System/nanoTime)))
|
(.addAndGet at (- t (System/nanoTime)))
|
||||||
r))
|
r))
|
||||||
([acc x]
|
([acc x]
|
||||||
(let [t (System/nanoTime)
|
(let [t (System/nanoTime)
|
||||||
r (rf acc x)]
|
r (rf acc x)]
|
||||||
(.addAndGet at (- t (System/nanoTime)))
|
(.addAndGet at (- t (System/nanoTime)))
|
||||||
r)))
|
r)))
|
||||||
rf (xform rf)]
|
rf (xform rf)]
|
||||||
(fn
|
(fn
|
||||||
([] (rf))
|
([] (rf))
|
||||||
([acc]
|
([acc]
|
||||||
(let [t (System/nanoTime)
|
(let [t (System/nanoTime)
|
||||||
r (rf acc)
|
r (rf acc)
|
||||||
total (.addAndGet at (- (System/nanoTime) t))]
|
total (.addAndGet at (- (System/nanoTime) t))]
|
||||||
(pt #?(:clj (* total 1e-6) :cljs total))
|
(pt #?(:clj (* total 1e-6) :cljs total))
|
||||||
r))
|
r))
|
||||||
([acc x]
|
([acc x]
|
||||||
(let [t (System/nanoTime)
|
(let [t (System/nanoTime)
|
||||||
r (rf acc x)]
|
r (rf acc x)]
|
||||||
(.addAndGet at (- (System/nanoTime) t))
|
(.addAndGet at (- (System/nanoTime) t))
|
||||||
r))))))))))
|
r)))))))))
|
||||||
|
|
||||||
#_(defn rollup
|
#_(defn rollup
|
||||||
"Roll-up input data along the provided dimensions (which are functions of one input item),
|
"Roll-up input data along the provided dimensions (which are functions of one input item),
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,13 @@
|
||||||
[net.cgrand.xforms.rfs :refer [or-instance?]])
|
[net.cgrand.xforms.rfs :refer [or-instance?]])
|
||||||
:clj (:require [net.cgrand.macrovich :as macros]))
|
:clj (:require [net.cgrand.macrovich :as macros]))
|
||||||
(:require [#?(:clj clojure.core :cljs cljs.core) :as core])
|
(:require [#?(:clj clojure.core :cljs cljs.core) :as core])
|
||||||
#?(:cljd (:require ["dart:math" :as Math]))
|
|
||||||
#?(:cljs (:import [goog.string StringBuffer])))
|
#?(:cljs (:import [goog.string StringBuffer])))
|
||||||
|
|
||||||
(macros/deftime
|
(macros/deftime
|
||||||
(defmacro ^:private or-instance? [class x y]
|
(defmacro ^:private or-instance? [class x y]
|
||||||
(let [xsym (gensym 'x_)]
|
(let [xsym (gensym 'x_)]
|
||||||
`(let [~xsym ~x]
|
`(let [~xsym ~x]
|
||||||
(if #?(:cljd (dart/is? ~xsym ~class)
|
(if (instance? ~class ~xsym) ~(with-meta xsym {:tag class}) ~y)))))
|
||||||
:default (instance? ~class ~xsym))
|
|
||||||
~(with-meta xsym {:tag class}) ~y)))))
|
|
||||||
|
|
||||||
(declare str!)
|
(declare str!)
|
||||||
|
|
||||||
|
|
@ -31,59 +28,40 @@
|
||||||
:else 0))))
|
:else 0))))
|
||||||
|
|
||||||
(defn minimum
|
(defn minimum
|
||||||
([#?(:cljd comparator :clj ^java.util.Comparator comparator :cljs comparator)]
|
([#?(:clj ^java.util.Comparator comparator :cljs comparator)]
|
||||||
(let [#?@(:cljd [comparator (dart-comparator comparator)] :default [])]
|
(fn
|
||||||
(fn
|
([] nil)
|
||||||
([] nil)
|
([x] x)
|
||||||
([x] x)
|
([a b] (cond
|
||||||
([a b] (cond
|
(nil? a) b
|
||||||
(nil? a) b
|
(nil? b) a
|
||||||
(nil? b) a
|
(pos? (#?(:clj .compare :cljs cmp) comparator a b)) b
|
||||||
(pos? #?(:cljd (comparator a b)
|
:else a))))
|
||||||
:clj (.compare comparator a b)
|
([#?(:clj ^java.util.Comparator comparator :cljs comparator) absolute-maximum]
|
||||||
:cljs (cmp comparator a b))) b
|
(fn
|
||||||
:else a)))))
|
([] ::+infinity)
|
||||||
([#?(:cljd comparator :clj ^java.util.Comparator comparator :cljs comparator) absolute-maximum]
|
([x] (if (#?(:clj identical? :cljs keyword-identical?) ::+infinity x)
|
||||||
(let [#?@(:cljd [comparator (dart-comparator comparator)] :default [])]
|
absolute-maximum
|
||||||
(fn
|
x))
|
||||||
([] ::+infinity)
|
([a b] (if (or (#?(:clj identical? :cljs keyword-identical?) ::+infinity a) (pos? (#?(:clj .compare :cljs cmp) comparator a b))) b a)))))
|
||||||
([x] (if (#?(:clj identical? :cljs keyword-identical?) ::+infinity x)
|
|
||||||
absolute-maximum
|
|
||||||
x))
|
|
||||||
([a b]
|
|
||||||
(if (or
|
|
||||||
(#?(:clj identical? :cljs keyword-identical?) ::+infinity a)
|
|
||||||
(pos? #?(:cljd (comparator a b)
|
|
||||||
:clj (.compare comparator a b)
|
|
||||||
:cljs (cmp comparator a b))))
|
|
||||||
b a))))))
|
|
||||||
|
|
||||||
(defn maximum
|
(defn maximum
|
||||||
([#?(:cljd comparator :clj ^java.util.Comparator comparator :cljs comparator)]
|
([#?(:clj ^java.util.Comparator comparator :cljs comparator)]
|
||||||
(let [#?@(:cljd [comparator (dart-comparator comparator)] :default [])]
|
(fn
|
||||||
(fn
|
([] nil)
|
||||||
([] nil)
|
([x] x)
|
||||||
([x] x)
|
([a b] (cond
|
||||||
([a b] (cond
|
(nil? a) b
|
||||||
(nil? a) b
|
(nil? b) a
|
||||||
(nil? b) a
|
(neg? (#?(:clj .compare :cljs cmp) comparator a b)) b
|
||||||
(neg? #?(:cljd (comparator a b)
|
:else a))))
|
||||||
:clj (.compare comparator a b)
|
([#?(:clj ^java.util.Comparator comparator :cljs comparator) absolute-minimum]
|
||||||
:cljs (cmp comparator a b))) b
|
(fn
|
||||||
:else a)))))
|
([] ::-infinity)
|
||||||
([#?(:cljd comparator :clj ^java.util.Comparator comparator :cljs comparator) absolute-minimum]
|
([x] (if (#?(:clj identical? :cljs keyword-identical?) ::-infinity x)
|
||||||
(let [#?@(:cljd [comparator (dart-comparator comparator)] :default [])]
|
absolute-minimum
|
||||||
(fn
|
x))
|
||||||
([] ::-infinity)
|
([a b] (if (or (#?(:clj identical? :cljs keyword-identical?) ::-infinity a) (neg? (#?(:clj .compare :cljs cmp) comparator a b))) b a)))))
|
||||||
([x] (if (#?(:clj identical? :cljs keyword-identical?) ::-infinity x)
|
|
||||||
absolute-minimum
|
|
||||||
x))
|
|
||||||
([a b]
|
|
||||||
(if (or (#?(:clj identical? :cljs keyword-identical?) ::-infinity a)
|
|
||||||
(neg? #?(:cljd (comparator a b)
|
|
||||||
:clj (.compare comparator a b)
|
|
||||||
:cljs (cmp comparator a b))))
|
|
||||||
b a))))))
|
|
||||||
|
|
||||||
(def min (minimum compare))
|
(def min (minimum compare))
|
||||||
|
|
||||||
|
|
@ -92,24 +70,23 @@
|
||||||
(defn avg
|
(defn avg
|
||||||
"Reducing fn to compute the arithmetic mean."
|
"Reducing fn to compute the arithmetic mean."
|
||||||
([] nil)
|
([] nil)
|
||||||
([#?(:cljd ^{:tag #/(List? double)} acc :clj ^doubles acc :cljs ^doubles acc)]
|
([^doubles acc] (when acc (/ (aget acc 1) (aget acc 0))))
|
||||||
(when acc (/ (aget acc 1) (aget acc 0))))
|
|
||||||
([acc x] (avg acc x 1))
|
([acc x] (avg acc x 1))
|
||||||
([#?(:cljd ^{:tag #/(List? double)} acc :clj ^doubles acc :cljs ^doubles acc) x w] ; weighted mean
|
([^doubles acc x w] ; weighted mean
|
||||||
(let [acc (or acc #?(:cljd (double-array 2) :clj (double-array 2) :cljs #js [0.0 0.0]))]
|
(let [acc (or acc #?(:clj (double-array 3) :cljs #js [0.0 0.0]))]
|
||||||
(doto acc
|
(doto acc
|
||||||
(aset 0 (+ (aget acc 0) w))
|
(aset 0 (+ (aget acc 0) w))
|
||||||
(aset 1 (+ (aget acc 1) (* w x)))))))
|
(aset 1 (+ (aget acc 1) (* w x)))))))
|
||||||
|
|
||||||
(defn sd
|
(defn sd
|
||||||
"Reducing fn to compute the standard deviation. Returns 0 if no or only one item."
|
"Reducing fn to compute the standard deviation. Returns 0 if no or only one item."
|
||||||
([] #?(:cljd (double-array 3) :clj (double-array 3) :cljs #js [0.0 0.0 0.0]))
|
([] #?(:clj (double-array 3) :cljs #js [0.0 0.0 0.0]))
|
||||||
([#?(:cljd ^{:tag #/(List double)} a :default ^doubles a)]
|
([^doubles a]
|
||||||
(let [s (aget a 0) n (aget a 2)]
|
(let [s (aget a 0) n (aget a 2)]
|
||||||
(if (< 1 n)
|
(if (< 1 n)
|
||||||
(Math/sqrt (/ s (dec n)))
|
(Math/sqrt (/ s (dec n)))
|
||||||
0.0)))
|
0.0)))
|
||||||
([#?(:cljd ^{:tag #/(List double)} a :default ^doubles a) x]
|
([^doubles a x]
|
||||||
(let [s (aget a 0) m (aget a 1) n (aget a 2)
|
(let [s (aget a 0) m (aget a 1) n (aget a 2)
|
||||||
d (- x m)
|
d (- x m)
|
||||||
n (inc n)
|
n (inc n)
|
||||||
|
|
@ -133,14 +110,9 @@
|
||||||
|
|
||||||
(defn str!
|
(defn str!
|
||||||
"Like xforms/str but returns a StringBuilder."
|
"Like xforms/str but returns a StringBuilder."
|
||||||
([] (#?(:cljd StringBuffer :clj StringBuilder. :cljs StringBuffer.)))
|
([] (#?(:clj StringBuilder. :cljs StringBuffer.)))
|
||||||
([sb] (or-instance? #?(:cljd StringBuffer :clj StringBuilder :cljs StringBuffer) sb
|
([sb] (or-instance? #?(:clj StringBuilder :cljs StringBuffer) sb (#?(:clj StringBuilder. :cljs StringBuffer.) (core/str sb)))) ; the instance? checks are for compatibility with str in case of seeded reduce/transduce.
|
||||||
(#?(:cljd StringBuffer :clj StringBuilder. :cljs StringBuffer.) (core/str sb))))
|
([sb x] (.append (or-instance? #?(:clj StringBuilder :cljs StringBuffer) sb (#?(:clj StringBuilder. :cljs StringBuffer.) (core/str sb))) x)))
|
||||||
; the instance? checks are for compatibility with str in case of seeded reduce/transduce.
|
|
||||||
([sb x] (doto (or-instance?
|
|
||||||
#?(:cljd StringBuffer :clj StringBuilder :cljs StringBuffer) sb
|
|
||||||
(#?(:cljd StringBuffer :clj StringBuilder. :cljs StringBuffer.) (core/str sb)))
|
|
||||||
(#?(:cljd .write :default .append) x))))
|
|
||||||
|
|
||||||
(def str
|
(def str
|
||||||
"Reducing function to build strings in linear time. Acts as replacement for clojure.core/str in a reduce/transduce call."
|
"Reducing function to build strings in linear time. Acts as replacement for clojure.core/str in a reduce/transduce call."
|
||||||
|
|
|
||||||
|
|
@ -97,42 +97,41 @@
|
||||||
|
|
||||||
#?(:bb nil ;; babashka doesn't currently support calling iterator on range type
|
#?(:bb nil ;; babashka doesn't currently support calling iterator on range type
|
||||||
:clj
|
:clj
|
||||||
(do
|
(deftest iterator
|
||||||
(deftest iterator
|
(is (true? (.hasNext (x/iterator x/count (.iterator ^java.lang.Iterable (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 ^java.lang.Iterable (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 ^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 ^java.lang.Iterable (range 5)))))))
|
|
||||||
|
|
||||||
(deftest window-by-time
|
(deftest window-by-time
|
||||||
(is (= (into
|
(is (= (into
|
||||||
[]
|
[]
|
||||||
(x/window-by-time :ts 4
|
(x/window-by-time :ts 4
|
||||||
(fn
|
(fn
|
||||||
([] clojure.lang.PersistentQueue/EMPTY)
|
([] clojure.lang.PersistentQueue/EMPTY)
|
||||||
([q] (vec q))
|
([q] (vec q))
|
||||||
([q x] (conj q x)))
|
([q x] (conj q x)))
|
||||||
(fn [q _] (pop q)))
|
(fn [q _] (pop q)))
|
||||||
(map (fn [x] {:ts x}) (concat (range 0 2 0.5) (range 3 5 0.25))))
|
(map (fn [x] {:ts x}) (concat (range 0 2 0.5) (range 3 5 0.25))))
|
||||||
[[{:ts 0}] ; t = 0
|
[[{:ts 0}] ; t = 0
|
||||||
[{:ts 0}] ; t = 0.25
|
[{:ts 0}] ; t = 0.25
|
||||||
[{:ts 0} {:ts 0.5}] ; t = 0.5
|
[{:ts 0} {:ts 0.5}] ; t = 0.5
|
||||||
[{:ts 0} {:ts 0.5}] ; t = 0.75
|
[{:ts 0} {:ts 0.5}] ; t = 0.75
|
||||||
[{:ts 0.5} {:ts 1.0}] ; t = 1.0
|
[{:ts 0.5} {:ts 1.0}] ; t = 1.0
|
||||||
[{:ts 0.5} {:ts 1.0}] ; t = 1.25
|
[{:ts 0.5} {:ts 1.0}] ; t = 1.25
|
||||||
[{:ts 1.0} {:ts 1.5}] ; t = 1.5
|
[{:ts 1.0} {:ts 1.5}] ; t = 1.5
|
||||||
[{:ts 1.0} {:ts 1.5}] ; t = 1.75
|
[{:ts 1.0} {:ts 1.5}] ; t = 1.75
|
||||||
[{:ts 1.5}] ; t = 2.0
|
[{:ts 1.5}] ; t = 2.0
|
||||||
[{:ts 1.5}] ; t = 2.25
|
[{:ts 1.5}] ; t = 2.25
|
||||||
[] ; t = 2.5
|
[] ; t = 2.5
|
||||||
[] ; t = 2.75
|
[] ; t = 2.75
|
||||||
[{:ts 3}] ; t = 3.0
|
[{:ts 3}] ; t = 3.0
|
||||||
[{:ts 3} {:ts 3.25}] ; t = 3.25
|
[{:ts 3} {:ts 3.25}] ; t = 3.25
|
||||||
[{:ts 3} {:ts 3.25} {:ts 3.5}] ; t = 3.5
|
[{:ts 3} {:ts 3.25} {:ts 3.5}] ; t = 3.5
|
||||||
[{:ts 3} {:ts 3.25} {:ts 3.5} {:ts 3.75}] ; t = 3.75
|
[{:ts 3} {:ts 3.25} {:ts 3.5} {:ts 3.75}] ; t = 3.75
|
||||||
[{:ts 3.25} {:ts 3.5} {:ts 3.75} {:ts 4.0}] ; t = 4.0
|
[{:ts 3.25} {:ts 3.5} {:ts 3.75} {:ts 4.0}] ; t = 4.0
|
||||||
[{:ts 3.5} {:ts 3.75} {:ts 4.0} {:ts 4.25}] ; t = 4.25
|
[{:ts 3.5} {:ts 3.75} {:ts 4.0} {:ts 4.25}] ; t = 4.25
|
||||||
[{:ts 3.75} {:ts 4.0} {:ts 4.25} {:ts 4.5}] ; t = 4.5
|
[{:ts 3.75} {:ts 4.0} {:ts 4.25} {:ts 4.5}] ; t = 4.5
|
||||||
[{:ts 4.0} {:ts 4.25} {:ts 4.5} {:ts 4.75}]]))))) ; t = 4.75
|
[{:ts 4.0} {:ts 4.25} {:ts 4.5} {:ts 4.75}]])))) ; t = 4.75
|
||||||
|
|
||||||
(deftest do-not-kvreduce-vectors
|
(deftest do-not-kvreduce-vectors
|
||||||
(is (= {0 nil 1 nil} (x/into {} (x/for [[k v] %] [k v]) [[0] [1]])))
|
(is (= {0 nil 1 nil} (x/into {} (x/for [[k v] %] [k v]) [[0] [1]])))
|
||||||
|
|
@ -140,11 +139,9 @@
|
||||||
|
|
||||||
(deftest sorting
|
(deftest sorting
|
||||||
(is (= (range 100) (x/into [] (x/sort) (shuffle (range 100)))))
|
(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))))))
|
||||||
(is (= (sort-by identity > (shuffle (range 100))) (x/into [] (x/sort-by identity >) (shuffle (range 100))))))
|
|
||||||
|
|
||||||
(deftest destructuring-pair?
|
(deftest destructuring-pair?
|
||||||
(let [destructuring-pair? #'x/destructuring-pair?]
|
(let [destructuring-pair? #'x/destructuring-pair?]
|
||||||
|
|
@ -158,9 +155,3 @@
|
||||||
'(a b) false
|
'(a b) false
|
||||||
'{foo bar} false
|
'{foo bar} false
|
||||||
'{foo :bar} false)))
|
'{foo :bar} false)))
|
||||||
|
|
||||||
(defmacro wraps-for-with-no-destructuring []
|
|
||||||
(x/into [] (x/for [x (range 5)] x)))
|
|
||||||
|
|
||||||
(deftest for-in-macro
|
|
||||||
(is (= [0 1 2 3 4] (wraps-for-with-no-destructuring))))
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue