@huxley I remember now one of the reasons I paused working on a transducer version: disjunctions.
I was taking a moment to play around with it. I ended up with something kinda gross like
(defn x-some [xg1 xg2]
(fn [rf]
(fn
([] (rf))
([acc] (rf acc))
([acc x] (rf (algorithms/mix ((xg1 rf) acc x) ((xg2 rf) acc x)))))))
where xg1 and xg2 are xform goals.Maybe this is fine since conjunctions are the most common and those play nicely with transducers.
but basically all we need to do is add the ability to use into [] at m/search and we get ~10-15% for free
:search
- `(mapcat
- (fn [~(:symbol ir)]
- ~(compile* (:body ir) fail kind))
- ~(compile* (:value ir) fail kind))))
+ (if (use-transduces?)
+ `(into []
+ (mapcat
+ (fn [~(:symbol ir)]
+ ~(compile* (:body ir) fail kind)))
+ ~(compile* (:value ir) fail kind))
+ `(mapcat
+ (fn [~(:symbol ir)]
+ ~(compile* (:body ir) fail kind))
+ ~(compile* (:value ir) fail kind)))))As for the rest, I haven't gotten that deep yet.
OK. Well, definitely continue to explore. π
How does sequence perform there?
if I remember correctly, identical to into []
The same is true for ...permutations-with-unselected, but there the speed gain is marginal.
(into [] ,,,) will make it eager, (sequence ,,,) will keep it lazy.
I donβt know of any situations where the size of the result set of search is infinite but one thing I can tell you is that the transducer version of mapcat can end up blocking in certain situations where there are infinite or extremely large intermediate results.
It can stay as it is, I'm just posting what I've observed π