6 ms·
Clojure user here since 2010(my earliest Clojure project on Github), and while I agree with the fun point, the iceberg wart for me at this point is the inelegan
by kelseyfrog 4y ago
Clojure user here since 2010(my earliest Clojure project on Github), and while I agree with the fun point, the iceberg wart for me at this point is the inelegance of the interface hierarchy and its structure behind the scenes.
Clojure's forward-facing interface (a hundred functions that operate on one data structure) ended up breaking down for me at some point and became 10 functions on 10 data structures and those data structures became AFn, APersistentSet, APersistentMap, APersistentVector, IFn, IPersistentSet, IPersistentMap, IPersistentVector, ITransientMap, ITransientVector, IndexedSeq, LazySeq, &c, &c, &c.
Maybe I started writing code wrong. Maybe I dived too deep into the internals, Maybe it was something else. But at the end, there wasn't one data structure, there were dozens and dozens each with justifiable differences, but even so, that's not what was advertised. It took a decade to reach that point and perhaps the vast majority of folks never will.
The sad part is that I know none of it is up for change without creating a Clojure2, and that highlights the problem. Why should changing the internals need to break backwards compatibility? There is one unspeakable reason: the illusion wasn't complete and they weren't really internals to begin with.
- rawoke083600 4y agoRight ! But you still had fun the last decade correct /s ? :P My "real response" to is, I haven't seen this complaint(concern) to this extend that you describe in the wild or in my own life. I've definitely not coded in Clojure long enough to have seen any of that like you have, thus far my experience has been good with 'just' using maps. I do feel my next "step-up" would be to incorporate something like SPEC or Mali to "define/check" the fields/structure of said maps.
- lenkite 4y agoLets say that someone wants to improve on Clojure and make a better functional, immutable LISP! What should they start with ? Some things I miss is type support (for easy refactoring, auto documentation and performance), (small) native compilation, support for mobile platforms and their UI's, first-class web-assembly support, real structs and misc things like performant implementations for `first`, `last` and other clojure functions, light-weight concurrency like Go, data-flow analysis and pipelines, etc. An example of clojure performance issues covered here: https://tech.redplanetlabs.com/2020/09/02/clojure-faster/ https://tech.redplanetlabs.com/2020/09/02/clojure-faster/ All that stuff above should be fixed at the language/stdlib level. But what is your take on what needs fixing ? What would have been your solution for the N data-structures/ M algo problem you mentioned above ?
- bcrosby95 4y agoIf you want an easy win, one thing Rich mentioned in a talk is - if he had to do Clojure all over again today - he would put transducers at the 'bottom'. For data transformation this makes the underlying collection type largely immaterial. > real structs I'm not even sure if value types are conducive towards immutable, persistent data structures. I'm certainly excited for project Valhalla but I'm not sure if Clojure, nor any Clojure-like JVM language, written in an idiomatic fashion, would really benefit from it. > light-weight concurrency like Go Project loom is already in preview mode. Lightweight concurrency is nearly here for any JVM language, and once it's fully released I will likely have zero reason to use core.async. > type support Static typing is A Thing you can choose to do, but I doubt you would get many daily Clojure users agreeing that it is "better". I think it's different and better in some circumstances but not necessarily others. It definitely feels trendy these days, sorta like how dynamic typing felt trendy 15 years ago.
- fiddlerwoaroof 4y agoYes on the type support not really attracting Clojure users. If you wanted to enable better refactoring, the thing to do would be to take more pages from other lisps and use the compiler to add more metadata to the runtime (in development mode at least) so that you can get better tracking of the language constructs.
- hota_mazi 4y agoClojure users fighting against static typing are on the wrong side of history. They are fighting a side for all the wrong reasons, and they will lose. There is a reason why all dynamically typed languages today are scrambling to add some form of static typing to their language, but never the other way around. Static typing does everything dynamic typing does, but better, faster, allow automatic refactoring, faster programs, better navigation, better documentation, better maintenance.
- epgui 4y agoI also believe the same thing. However, to be fair, Clojure's response to types is `org.clojure/spec.alpha`, and if you give it a really good chance, you'll see that it brings a lot to the table. It doesn't change that I believe strong typing (a Haskell or Idris/Agda-like flavour of it) to be the future, but what it did change was how I thought about type systems and how to write and test programs.
- roenxi 4y agoAn interesting complaint. What problem domain(s) do you work in? It sounds like you've found something that Clojure isn't a great fit for. The mix of interfaces would be a huge pain if you needed their specific behaviours, but in my experience they've never mattered and lings like LazySeq just act as performance optimisations.
- yenda 4y agoDo you have some os projects out there to share where you had to do that? Makes me curious, I think the only time I've ended up making a specific data structure in clojure was for a library for perf reasons. In application code basically never.
- deleted 4y ago[deleted]
- kelseyfrog 4y agoSpecifically it was using GraalVM to interop Clojure on one side with React running on GraalJS on the other. It definitely pushed the limits of what is or even ought to be possible, but at the same time highlighted those very issues. I'll be the first to admit that this is an extreme edge case, but that doesn't take away from the fact that the case is still there.
- seancorfield 4y agoI've been programming with Clojure since 2010 and using it in production almost as long and I hardly ever care about the internal types so I'm really curious as to how you went down that "rabbit hole"? What sort of problems were you solving that necessitated delving into the implementation details behind the abstractions? I've only needed to dig into that occasionally for a handful of specific situations (for example, in next.jdbc, where I create a hash map like abstraction over the (mutable) ResultSet object from Java -- to paper over some nasty interop issues).
- zx8080 4y agoWhat is the idea behind immutable variant of a ResultSet? Since it maintains a database cursor, does it make sense to have it immutable? > A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row [0] 0 - https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet...
- seancorfield 4y agoIf you're a Clojure developer and you're using the next.jdbc library you don't need to ask that question :)
- zx8080 4y agoObviously, I'm not :)