I think I've found a bug in clojure 1.11. No minimal repro yet, but this is a repro, it worked under 1.10:
(def flatten
"A transducer version of clojure.core/flatten"
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (sequential? input)
(transduce flatten rf result input)
(rf result input))))))
(into [] flatten [[1] [2] [3]]) ;; => boomI would guess it's https://clojure.atlassian.net/browse/CLJ-2556 ?
What is the exception?
Execution error (ClassCastException) at user/flatten$fn (REPL:10).
class clojure.lang.PersistentVector cannot be cast to class clojure.lang.ITransientCollection (clojure.lang.PersistentVector and clojure.lang.ITransientCollection are in unnamed module of loader 'app')
Switching impl to this seems to fix it:
(def flatten
"A transducer version of clojure.core/flatten"
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (sequential? input)
(reduce (flatten rf) result input)
(rf result input))))))Probably not correct though, because I'm not using all the arities.
there were some changes in into completion
I'm not sure your code is right wrt reduced
if the inner reduce returns a reduced, you need to wrap in a second reduced (see cat impl)
You're right, I think that's broken. But I don't think that's the problem in this case.
into didn't introduce a reduced. I think the problem is that there's now an official completion which calls persistent . And by using rf with transduce we are completing earlier than expected now.
yeah, I think that makes sense based on the exception
(def flatten
"A transducer version of clojure.core/flatten"
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (sequential? input)
(transduce flatten (completing rf) result input)
(rf result input))))))
Does the trick. But tbh, I think my original decision to just turn it into an rf and use reduce is probably more correct now I understand it. We are trying to recursively reduce. We just got lucky that the completion has done nothing in context up until now.