3 ms·
I’m in the opposite boat. I went from Clojure to Java. I got really tired of “finishing” my work, only to discover that it was riddled with bugs from all kinds
by ashtonkem 6y ago
I’m in the opposite boat. I went from Clojure to Java.
I got really tired of “finishing” my work, only to discover that it was riddled with bugs from all kinds of weird edge cases. My favorite is having to use (map vec <thing>) all over the place, because the seq abstraction leaks like a sieve.
To be fair, I also worked in a domain that was extremely poorly suited to Clojure. The “data first” approach of Clojure falls to pieces the moment you have a bunch of data that’s syntactically similar, but semantically different. This requires a lot of cross-method coordination, creating a huge mess and a risk of missed cases.
- Naomarik 6y agoEveryone's problems, context, and experience is different, but from where I stand it sounds like you may have had an a better experience using a data spec library like Metosin's malli. One of the pain points I had before was different kinds of data flowing through my system. Clojure spec never made complete sense to me and was a bit difficult to write specs that matched my data. It was easier to write data that matched the specs. Malli does this a lot more easily with human errors that have made my life enormously easier. It's been a game changer for me.
- ashtonkem 6y agoI don’t know Malli; and I haven’t used Clojure since 2017, so things might have changed. So if I’m misunderstanding the purpose of that library, my mistake. The issue wasn’t that we would use the wrong data in the wrong place. The issue is that we had a bunch of data that was syntactically similar (huge overlap in keys), but semantically different (key numerical results must be calculated differently based on the minor differences between maps). So the issue is less “the right data got to the wrong place” and more “in this data pipeline there are multiple places where the same data must be treated differently based on minor differences”. This is actually pretty tricky to do in a maintainable way in Clojure; technically possible but really hard to avoid breaking when you need to extend it. In the end it actually turned out to be an issue that classes and objects solved brilliantly. The solution was to have the pipeline accept an interface (syntactic similarity) and have different classes for the behavior (semantic differences).
- zeugmasyllepsis 6y agoThis reminds me of a discussion between Alan Kay and Rich Hickey on role of "data" that occurred right here on HN[1]. The TLDR (though the thread is very worth reading, IMO): Alan Kay argues that bare "data" isn't very meaningful on its own because it leaves the interpretation too open. His view is nicely summarized by the following quote: > For important negotiations we don't send telegrams, we send ambassadors. Rich Hickey argues that bare "data" is a fundamental primitive that, while leaving open the possibility of misinterpretation, leaves open the possibility of re-interpretation in multiple contexts. This is the strongest quote I took away from his POV: > None of the inputs to our sensory systems are accompanied by explanations of their meaning. Based on your above post, it looks like you're strongly in Alan Kay's camp, which may also explain (in part) your experience struggling with Clojure's approach. [1] https://news.ycombinator.com/item?id=11945722 https://news.ycombinator.com/item?id=11945722
- ashtonkem 6y agoThat is a very succinct summary, yes. I’ll add that certain applications are more amenable to one kind of use or another. I find the possibility of re-interpretation utterly bewildering. I have never re-interpreted my data in Clojure application, at least not in any way that I understand that word. Rewrite algorithms, yes, but you can do that in any language. The only time I think of re-interpreting data in a different context is in a data lake or similar, which is a wildly different thing, IMHO.
- onetom 6y agoThis sounds fishy to me too... Have you actually consulted anyone, with more Clojure experience, how to avoid the need for `(map vec <thing>)` all over the place? I would guess you were working with deeply nested data structures and you had to do deep updates, while strictly maintaining the vector data-type. That's indeed kinda sucky to do just using vanilla `clojure.core`, indeed, but then there is https://github.com/redplanetlabs/specter https://github.com/redplanetlabs/specter for that. Alternatively, instead of dealing with deep nesting, you should probably work with namespaced keys, which allow flattening your data and suddenly a lot of transformations become radically simpler and such a system is more extensible too...
- ashtonkem 6y agoYour attitude is extremely patronizing.