Skip to content

Instantly share code, notes, and snippets.


ghadishayban/into.clj Secret

Last active Sep 18, 2020
What would you like to do?
;; 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)
([] (transient to))
([tcoll] (with-meta (persistent! tcoll) (meta to)))
([tcoll item] (conj! tcoll item)))
([] 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