5 ms·
With respect, this topic in particular has been beaten to death. I too liked Clojure when I tried it some years ago (agreed on the composition and data structu
by pdimitar 4mo ago
With respect, this topic in particular has been beaten to death.
I too liked Clojure when I tried it some years ago (agreed on the composition and data structures; both are _great_). But the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang -- I am talking concurrency / parallelism here (for memory management I have no doubts Java is very good). And I know: green threads and stuff. Well, call me when you can do what Erlang / Golang can do. Then I'll look again, very seriously too.
Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for.
- iLemming 4mo ago[flagged]
- bcrosby95 4mo agoWhen it comes to concurrency, what can golang's runtime do that is so special? When I tried it, it seemed like a worse version of Erlang's for people that prefer C style syntax. Depending upon your design space pervasive immutability is a huge boon too and golang doesn't have that but Clojure does - Erlang obviously having that and more. I always wished clojerl took off.
- pdimitar 4mo agoI agree Golang is a worse version of OTP, no question about it, but if you are not allowed to code in Erlang/Elixir/Gleam (which sadly is 99.9% of the projects on the planet) then Golang is the next best thing. It has footguns, sure, but with library support and discipline it can get you very far. To me it's embarrassing that PLs still tout syntax and various other goodies, completely glossing over runtime. I might be missing something. But faux humble statements aside, I feel many others are the ones who miss something -- and that's the fact that doing stuff in parallel is a fact of life for 20+ years now and it's time all popular PL runtimes finally wake up to that fact. If not, I am simply not considering them. And I am not saying that arrogantly though it sounds that way; there are some PLs that I _really_ liked and was almost heart-broken that I had to abandon them and not work professionally with them. But I have enough experience to know that runtime choice matters, a lot. For the record, Racket was one of those PLs I abandoned. I know they started working on parallelism some years ago but I had to make a decision next week back then so, Elixir + Golang + Rust it is for me.
- agambrahma 4mo agoYeah, the content + feel felt like I'm reading this in 2013. Nothing wrong with that, it's a good thing that stuff is discovered anew [as opposed to being lost/forgotten], but it did bring a smile to me.
- chamomeal 4mo agoAre JVM virtual threads not on par with golangs's concurrency? I think core.async even uses virtual threads now
- pdimitar 4mo agoIf they are, I have not heard about it (which does not mean much, I check Java once a year). And if they really are then I'd give Java a serious look again because it's a mature ecosystem that was gimped by ancient runtime decisions for literal decades.
- cogman10 4mo agoAs of Java 24 (Java 25 being an LTS) I'd say they are equivalent. You can use a virtual thread just like you use a regular thread and there's basically no handicaps or gotchas. In Java 21, when they were released, there is a gotcha that the pretty normal use of the `synchronized` keyword would pin a "carrier thread" which ends up blocking all virtual threads from running on that carrier thread. Pinning can still happen in some much more rare cases, same with go. For example, FFI. The memory usage, performance, etc are all go like. You can spawn millions of virtual threads with hardly and memory requirements and without overburdening the OS with context switches. The JVM also enjoys faster GC performance with virtual threads.
- raspasov 4mo ago^^^ This.
- vips7L 4mo agoYour knowledge is outdated. Go check again.
- weavejester 4mo ago> Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for. I'm not sure I understand this argument. Java and Clojure share a runtime, but an idiomatic Java codebase is going to have a very different architecture and design to an idiomatic Clojure codebase. Conversely, a codebase written in Go may end up looking very similar to a codebase written in Java, despite using different runtimes.
- pdimitar 4mo agoI mean runtime guarantees and features. In this case: effortless / near-invisible concurrency and parallelism. As mentioned, I did like Clojure. I'd switch to it if it was running inside the Erlang runtime (like Elixir does).
- weavejester 4mo agoTo be clear, I'm not questioning your choice of runtime or language. I'm just curious why you think that "Programming language syntax scarcely matters", as to me that seems the same as saying "How a codebase is architectured and designed scarcely matters".
- pdimitar 4mo agoI don't see how the latter follows from the former? The former is much bigger and more abstract; syntax is just one of the vehicles to try and codify it. F.ex. if you have an universal construct of green threads / fibers then 7 PLs could express it 7 different ways, yet underneath they'd all be the same.
- weavejester 4mo agoThe programming language informs the design of the system. As I said in my earlier comment, an idiomatic Java codebase is going to be designed very differently to an idiomatic Clojure codebase, even if they both intend to solve the same problem.
- TacticalCoder 4mo ago> Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for. But that really depends on what you're doing. For example if I'm not mistaken Amazon was run for a very long time on a Java backend. And so was GMail's backend (and back then GMail's frontend was, IIRC, Java converted to JavaScript using GWT). And by "early Amazon" and "early GMail", we're already talking about massive scale. It's not as if the JVM got worse since then (as someone commented: a recent addition is that Clojure now use Java's virtual threads) and it's not as if it didn't scale. So I'd say having Clojure on top of Java (for those using that Clojure: there's also ClojureScript, babashka, etc.) ain't really a problem, as long as you're fine with the occasional Java stacktrace and Java ecosystem (GP mentions that btw: that he's not familiar with Java and that, I think, can be a bit of an issue). I'm not sure Clojure is about it's syntax: I like the focus on immutability / pure functions and I do really dig the REPL a huge lot. In addition to that something has to be said as to the incredible stability of the language and many of its libraries. The big value add to me is that I can have a REPL and inspect, in dev (or in prod but that'd be wild), the app I'm working on. And manipulate it: redefining variables and functions etc. And it's not some hacky hot-reloading bolted on as an afterthought kludge: it's a real Lisp REPL. There's value in that IMO.
- pdimitar 4mo agoElixir has all that _and_ Erlang OTP's amazing guarantees. Hence I landed on it. Elixir also offers LiveBooks i.e. you can create pre-made recipes with which you directly remote into your staging / prod and do stuff. All that with immutability and potentially 6 digits of actors / green threads with a share-nothing architecture. --- RE: early Amazon / Google, sure. They made do with what they had and it was and still is a heroic effort. But can we agree that they succeeded _despite_ the numerous warts and defects of the PLs and their runtimes at the time? Not _because_ of them? I feel that people latch onto the misleading "they succeeded with language X and are big, hence the language X is great" thing way too often. No. It's not true. The only thing that follows from "big company A made it big with language X" is: "company A has an amazing engineering team". Nothing else.
- scruple 4mo agoHave you tried Lisp Flavored Erlang [0]? I never got around to trying it out. I used Elixir for a couple of years, building web backends, and I truly loved the experience. I remember wanting to try out LFE but never got around to it before moving on to a different employer/stack. [0]: https://en.wikipedia.org/wiki/LFE_(programming_language) https://en.wikipedia.org/wiki/LFE_(programming_language)
- pdimitar 4mo agoI have and I did kind of like it but ultimately admitted to myself that I no longer want to use too niche or too new PLs. Elixir has a fairly solid ecosystem at this point and I am only going to switch to something even bigger (I already use Goland and Rust as well). Love the idea of LFE but it needs a bigger ecosystem.
- raspasov 4mo agoWhat can the Erlang / Golang runtimes do that the JVM can’t?
- pdimitar 4mo agoThousands of share-nothing actors (fibers / green-threads) with first-class support for communication between them, for a start. Erlang/Elixir -- immutability as well.
- lgrapenthin 4mo ago"As a rule of thumb, if your application never has 10,000 virtual threads or more, it is unlikely to benefit from virtual threads." https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html https://docs.oracle.com/en/java/javase/21/core/virtual-threa...
- pdimitar 4mo agoObviously. But it's really nice to have the option, and none of us knows the future. I've been bitten by those "0.1% chance" things much more times than I would be not-embarrassed to admit, and I know I a not alone.
- andersmurphy 4mo agoI believe the point they were making is you can have millions of virtual threads on the JVM no problem. Your information on the JVM is outdated.
- pdimitar 4mo agoGood, thanks for the grounding. I'll have to reevaluate at one point then. As I just posted in another comment (https://news.ycombinator.com/item?id=48384622 https://news.ycombinator.com/item?id=48384622), I'd probably drop Erlang/Elixir due to difficulties of employment and contracting -- if the more popular languages get those STM / share-nothing runtimes.
- manoDev 4mo ago> Programming language syntax scarcely matters. Clojure brings more than syntax though... there's an opinionated take on making all data structures immutable (as in, structural sharing [1]) by default. That's a huge difference in how you architect the program and debug it. [1] https://softwarepatternslexicon.com/clojure/core-concepts-of-clojure/immutable-data-structures/ https://softwarepatternslexicon.com/clojure/core-concepts-of...
- pdimitar 4mo agoI do love immutability. If a language does not have it I am very weary of using it. I only made exception of Rust because of how good is it for so many things + you can design with immutability first and only use mutability when you truly have no other choice and/or just want more performance and are willing to shoulder the extra effort of verification (potentially fuzzy testing even).
- lgrapenthin 4mo agoClojure is about its rigorous and pragmatic "immutability first" paradigm that you simply don't get from other PLs. LISP is much more than just a runtime syntax, such as its distinct evaluation model and metalinguistic core. The JVM was chosen for Clojure because of its reach and vast ecosystem. People have ported Clojure to other runtimes, even Beam (Clojerl), where it enjoys decent success, too.
- pdimitar 4mo agoAll true. And I loved trying Clojure for 3-4 weeks some years ago. Still want Erlang's runtime though i.e. the many green threads with share-nothing architecture that can communicate with each other.
- sorry_i_lisp 4mo agoClojure on JVM with virtual-threads (green threads) and communicating only via core.async channels (CSP inspired) using immutable data structures is pretty neat, FWIW.
- pdimitar 4mo agoCool. I might have to revisit, if I ever find the time. Thanks, your comment aligns with what multiple other commenters expressed. Info gets stale. Fair.
- thaumasiotes 4mo agoYou don't think Erlang has an "immutability first" paradigm?
- IsTom 4mo agoErlang is weird in this regard. It has very strong guarantees when it comes to per-process heap that make GC much simpler: no escape hatches for mutability when most immutable languages do include them! But on the other hand inter-process communication is a form of mutability (using another process as a global mutable variable is trivial) and ETS etc. present a mutable interface.
- bsder 4mo ago> Programming language syntax scarcely matters. Certainly it matters much less in the modern era. However, certain fundamental decisions of a language can be dealbreakers. Requiring declarations on your functions and giving those declarations sigils so that they can be parsed quickly is an important syntax decision. Almost every modern programming language has converged to this idea. Or take, for example, Lua. For me, personally, the 1-based-ness of Lua is simply a dealbreaker no matter how good anything else about it is. For the "Lisps", I LOATHE the fact that you traverse lists and vectors in completely different ways--you can't just drop any container-ish thing into something that iterates/collects it. This is something that both Clojure and Racket seem to agree on--you have something that acts like a "collection" and you can walk across it the same way regardless of the specific type of collection it is. Of course, that is why a bunch of Lisp purists loathe Clojure and Racket while I like those languages. Shrug. I find RAII (Resource acquisition is initialization) to be the source of all things evil if it infests a programming language. The popularity of C++ and Rust speaks to the quite large number of people who think my opinion is bullshit. So, yeah, base syntax matters far less than it used to. But the engineering decisions that went into making that syntax correspondingly are far more important.
- pdimitar 4mo agoI think we can easily agree they are two entities (syntax / runtime) that feed off of each other. And I do agree that previously the syntax mattered more. (I very much agree on Lua btw.) Personally I am very disheartened. Surely algebraic data types should be universally a good thing and all PLs should gradually adopt them? But no, endless HN / Reddit threads bike-shedding. Oh well.
- adrian_b 4mo agoI agree with most of what you said, but I am puzzled about your claim about RAII. Whether it is good for any kind of resource acquisition to look the same like an initialization is debatable. On the other hand, I cannot see any counterargument to the principle that releasing any resources should not be done explicitly, but only implicitly, upon leaving a block (using reference counts for shared resources). I doubt that you advocate for the use of explicit release commands for resources, which are a notorious source of bugs, so what is that you consider as not being the same as RAII? RAII was a not very useful acronym that was just another form to say that the C or C++ programmers should never use the PL/I style of explicit free commands, despite the availability of functions like "free()" or "close()" in the standard library, but both memory and files and any other kinds of resources should be managed with automatic releasing. I do not see how this sound principle can infest any language. Obviously, I have seen examples of bad RAII implementations, like I have seen examples of misuse for any other programming principle.
- dundunUp 4mo agoYeah, the content + feel felt like I'm reading this in 2013.
- beders 4mo agoGood thing you have a variety of those nowadays. Clojure runs in the browser, Node.js, cross-compiles to Dart, works stand-alone via babashka and has a brand new C++ interfacing implementation in Jank. The ergonomics of using a proper REPL and interactive programming is hard to beat.
- deleted 4mo ago[deleted]
- midnight_eclair 4mo ago> the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang won't lie, this is hilarious. you got me from nodding along to being the spitting out food meme guy in a span of couple seconds. JVM runtime is undeniably the most well researched and optimized runtime in history of runtimes, specifically in realm of concurrency and parallelism, it literally carries like half the world on it's back. not to throw any shade on erlang vm - i've been a fan for well more than a decade, but other than making some interesting, but limited in practice, tradeoffs with regard to concurrency architecture, it doesn't really offer much more. go's runtime is just a different beast altogether designed with different goals in mind and with no baggage of backward compatibility with legacy. one particular detail i'm very grateful to Clojure for, is exactly the ability to use JVM runtime without having to touch any Java. > Programming language syntax scarcely matters on the contrary, it matters quite a lot. you might be drinking some of that AI koolaid, conflating our suddenly hypertrophied abilities to produce code regardless of our familiarity with the syntax or the APIs with ability to produce and deliver good quality products, but this delusion is getting reality check as we speak. a realization is propagating through the industry that being able to produce more code than you're able to review, comprehend and internalize is actually not a great thing. and that's where syntax matters - it has to be high signal/noise, it has to expose you to right abstractions and it has to be pliable to allow the codebase reflect the problem in a way that minimizes cognitive load both during production and during consumption. LLMs are language models and syntax is a crucial part of any language.
- pdimitar 4mo agoWell, you are kind of using my comment to vent your frustrations about AI while it has barely anything to do with it -- but you tried to link the two, unsuccessfully. Which is not fair as you have no clue of my stance on AI and are extrapolating a bit too much. Syntax does not matter simply because it's an extremely leaky abstraction of the runtime below, is my point. Of course syntax must be high signal/noise ratio, I believe every reasonable programmer will agree. But many are making entire careers in PLs where that's not the case. Hence, in practice it does not seem to matter much, for the better or the worse. RE: runtime, try and pay attention to the parameters given in my comments. I specifically acknowledged that the JVM is a great and mature runtime but it's lagging behind on STM / actor capabilities. Tearing down a straw man is not impressive and it comes across as you trying to gain visibility by deliberately misrepresenting your discussion opponent's arguments.
- DarkNova6 4mo agoI think you might reevaluate the runtime claim, since the JVM is perfectly capable of stackful coroutines these says.
- wellpast 4mo agoNot even to optimize for, but to write correct programs you really need to understand the runtime which is usually broader than the syntax. All Clojure (lisps) do is remove the stupidity of syntax. Even if syntax is the minor thing, why wear a stupid, uncomfortable shirt while running when you could wear one so comfortable you scarcely feel it?
- pdimitar 4mo agoWell I agree, that's why I use Elixir and not its underlying Erlang. And I agree that most LISPs remove the stupidity of syntax. Very true.
- regularfry 4mo ago> With respect, this topic in particular has been beaten to death. Yes and no. From the discussion here I've learned about the existence of jank, which wouldn't have come up a year or so ago and might be an interesting solution to a problem for me as it evolves (that problem mainly being me not wanting to use C++ or any of the other directly supported languages in a plugin ecosystem). So these things are worth bubbling up every now and again just for the discussion to have a chance to play out.
- foxygen 4mo agoThe JVM is perfectly capable of Golang-style green threads now. As for Erlang, the creator of Clojure have commented in the past on why he dislikes the Actor model, and I think it is a fair criticism. Sometimes I see people praising Erlang VM as some panacea in which all the VMs should strive to be like. This is overly simplistic in my opinion, and ignores the huge trade-offs that the Erlang VM has.
- pdimitar 4mo agoYou might be speed-running to a conclusion and squinting too hard if you use the word "panacea". Similar to the weird childish name-calling people do in Rust threads (somebody met one brainless zealot and now of course they'll judge a community of hundreds of thousands of devs by that one loony). I used Java, Golang, Rust, Elixir (so Erlang). My opinion is informed. STM / share-nothing-actors lend themselves amazingly well to online services for many reasons, better explained by other people and documented elsewhere (and I did not come here to advocate but to express preference and offer the take of somebody who has been around). I am not denying that the JVM might have almost caught up in the meantime. More than a decade ago it did not. And yes the BEAM VM is absolutely and markedly _not_ a panacea. It has a few weird sharp edges. It's just that in my work I have found having to avoid them still worth it compared to the alternatives (global mutability and more primitive parallelism which was the case for the JVM for decades).
- foxygen 4mo agoI have used Clojure(JVM), Elixir(so Erlang) and a bit of Golang professionally too. So my opinion "is informed" too for that matter, but this kind of appeal to authority adds nothing to the discussion. > I am not denying that the JVM might have almost caught up in the meantime. More than a decade ago it did not. This presupposes that the JVM had something to catch up in the meantime. Again, this lacks nuance and brings nothing to the table. The JVM makes different trade-offs than the Erlang/Golang VM does, and has different strengths and weaknesses. Both of your comments completely ignores that. > It's just that in my work I have found having to avoid them still worth it compared to the alternatives (global mutability and more primitive parallelism which was the case for the JVM for decades). Clojure runs on the JVM and avoids mutability pretty well. It is amazing for writing concurrent software, and has been for many years(i.e more than a decade ago). > Similar to the weird childish name-calling people do in Rust threads I've seen people do similar things to the JVM.
- djblue 4mo agoI think one of Clojure's main strengths for concurrency / parallelism is structural sharing of immutable data across threads, which you simply cannot do in Erlang.
- pdimitar 4mo agoI kind of agree. Erlang took the "share nothing" thing to extremes by copying everything which, while improving memory safety by a huge margin, introduced (a) various GC footguns (like the shared big binaries gated behind refcounting which is a famous footgun for very long-running apps) and (b) reduced its raw speed.