into
;; clojure.core/into | |
;; into passes conj! to transduce, then tries to complete the return on the _outside_ of transduce | |
;; halt-when overrides return of transduce with a persistent vector | |
(defn into | |
"Returns a new coll consisting of to-coll with all of the items of | |
from-coll conjoined. A transducer may be supplied." | |
;; elided | |
([to xform from] | |
(if (instance? clojure.lang.IEditableCollection to) | |
(with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to)) ;; persistent! is really a rf completion | |
(transduce xform conj to from)))) | |
user=> (into [] (halt-when #{:anomaly} vector) [1 2 :anomaly 3 4]) | |
Execution error (ClassCastException) at user/eval1 (REPL:1). | |
class clojure.lang.PersistentVector cannot be cast to class clojure.lang.ITransientCollection | |
;; instead, add a completion arity to the reducing fn which that calls persistent! and reattaches meta | |
(defn into | |
[to xform from] | |
(let [rf (if (instance? clojure.lang.IEditableCollection to) | |
(fn | |
([] (transient to)) | |
([tcoll] (with-meta (persistent! tcoll) (meta to))) | |
([tcoll item] (conj! tcoll item))) | |
(fn | |
([] to) | |
([coll] coll) | |
([coll item] (conj coll item))))] | |
(transduce xform rf from))) | |
;; look ma, now halt-when can receive a completed persistent value, not a transient | |
user=> (into [] (halt-when #{:anomaly} vector) [1 2 :anomaly 3 4]) | |
[[1 2] :anomaly] | |
user=> (into [] (comp (halt-when #{:anomaly} vector) (map str)) [1 2 :anomaly 3 4]) | |
[["1" "2"] :anomaly] | |
;; this also means that halt-when can return a differently shaped thing from into's 'to' argument | |
;; which can make sense when processing anomalies | |
user=> (into [] (halt-when :anomaly #(assoc %2 :partial-results %1)) [1 2 {:anomaly :oh-no!} 3 4]) | |
{:anomaly :oh-no!, :partial-results [1 2]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment