Hacker News new | ask | show | jobs
by kimi 1049 days ago
Not sure if the "transducer" approach suggested as a workaround makes your life easier or further adds to the mental overhead. See https://www.astrecipes.net/blog/2016/11/24/transducers-how-t... for some example transducers.
2 comments

Using transducers is really easy and intuitive (with "comp" letting you compose a pipeline of transformations in a readable way).

Writing custom transducers, especially stateful transducers is really difficult. But that's not something you'll do often. My 10kLOC complex app has three stateful transducers that I wrote.

I think transducers are an under-appreciated aspect of Clojure. They are an extremely valuable and flexible tool, and have allowed me to write reusable and composable code and tackle significant complexity, all with great performance.

Yes I agree with you that transducers are OK. I think that they miss a bit in ergonomics, not power.
Transducers aren’t just faster, they offer more functionality, with the ability to reuse the logic no matter where your inputs and outputs are coming from. So it’s no real surprise that there’s more implementation complexity. Client code isn’t much more complex, and arguably lower mental overhead because you can give stacks of transducers names without having to introduce a whole new function with a sequence as an argument.

Obviously in languages that can reliably perform stream fusion transparently, maybe you care less, but the abstraction isn’t just about the speedup.

I saw this a couple of days ago somewhere and I think it belongs in the discussion between lazy-seqs and transducers: https://en.wikipedia.org/wiki/Waterbed_theory

You can't hide from complexity. It will lurk somewhere anyway.

Yup. And to be honest there’s a bunch of additional complexity in Clojure transducers that I very much dislike (all the reducing function stuff which is almost never actually used and which is secondary to the purpose of creating a sequence transform via function composition). But it’s a tradeoff you make for additional functionality or speed. Or you move complexity to reduce cognitive overhead for certain use cases. There’s rarely a free lunch.