clojure-dev

dominicm 2022-07-08T03:07:39.891649Z

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]]) ;; => boom

dominicm 2022-07-08T03:10:16.472739Z

I would guess it's https://clojure.atlassian.net/browse/CLJ-2556 ?

2022-07-08T03:13:38.590959Z

What is the exception?

dominicm 2022-07-08T03:14:49.104799Z

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))))))

dominicm 2022-07-08T03:16:12.413019Z

Probably not correct though, because I'm not using all the arities.

Alex Miller (Clojure team) 2022-07-08T03:23:30.587599Z

there were some changes in into completion

Alex Miller (Clojure team) 2022-07-08T03:24:03.243339Z

I'm not sure your code is right wrt reduced

Alex Miller (Clojure team) 2022-07-08T03:24:57.309239Z

https://clojure.atlassian.net/browse/CLJ-2556

Alex Miller (Clojure team) 2022-07-08T03:31:46.382789Z

if the inner reduce returns a reduced, you need to wrap in a second reduced (see cat impl)

dominicm 2022-07-08T03:32:37.318389Z

You're right, I think that's broken. But I don't think that's the problem in this case.

dominicm 2022-07-08T03:33:45.032479Z

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.

Alex Miller (Clojure team) 2022-07-08T03:34:04.514289Z

yeah, I think that makes sense based on the exception

dominicm 2022-07-08T03:36:19.303579Z

(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.