[HN Gopher] Why Clojure?
       ___________________________________________________________________
        
       Why Clojure?
        
       Author : jgrodziski
       Score  : 103 points
       Date   : 2025-02-22 09:44 UTC (1 days ago)
        
 (HTM) web link (gaiwan.co)
 (TXT) w3m dump (gaiwan.co)
        
       | fithisux wrote:
       | Now LISP has the big three. CL, Scheme and Clojure. Each
       | introduces a fundamentally different way of thinking and all come
       | from standards or standard implementations. There is also
       | Newlisp, more akin to R and Julia and other LISPs each bringing
       | some new things on the table. Still you need to have an idea from
       | the big three to appreciate what LISP is all about.
        
       | moi2388 wrote:
       | Because you want the type safety of lisp with the simplicity of
       | the jvm /s
        
         | gleenn wrote:
         | You are being snarky but I'll take immutability over types and
         | interoperability and access to a vast and stable ecosystem over
         | the simple and extremely limited and underperforming
         | alternatives. Thanks for the segway. I also cannot understate
         | the reasoning ease that comes with basically everything being a
         | static, top-level function. Testing never requires mocks
         | because you can redef any function anywhere trivially when you
         | otherwise would reach for a mock which tends to be painful,
         | complicated, and requires comlex mocking libraries. Even with
         | immutability by default, you get an extremely performant
         | platform that usually stomps on nearly all the dynamic
         | languages you might otherwise choose like Python or Ruby etc.
         | And you get first-class functions and a concise and extremely
         | stable language that is a joy to program in. Thanks Rich and
         | Alex!
        
           | AnimalMuppet wrote:
           | > I'll take immutability over types and interoperability
           | 
           | OK.
           | 
           | > Thanks for the segway.
           | 
           | A segway is a motorized transport; a segue is a transition to
           | a different topic. So this could be considered a type error,
           | and demonstrates why you need types, not just immutability.
        
             | slowmovintarget wrote:
             | While amusing, I still disagree.
             | 
             | Complex static type syntax ends up infecting your code,
             | because the syntax becomes load-bearing. A change to one
             | type has a tendency to ripple through the entire body of
             | code. This means you have tight coupling as a consequence
             | of the syntax, which is a bad trade-off. Clojure's strong
             | dynamic abstract types allow you to focus on the function
             | of the code instead of its structure. Trying things out in
             | the REPL first helps you find many of the things that you
             | might need to wait for a compiler to find.
             | 
             | There are studies that estimate that the kind of bugs
             | shipped to production that strong static types help prevent
             | account for only 2% of defects. The rest are things like
             | off-by-one errors, design errors, and incorrect logic.
             | 
             | The other thing a static type system can help you with is
             | reading code. But it's primarily an aid to people
             | unfamiliar with the language, or put in more popular
             | parlance a "skills issue." We know tooling can navigate the
             | code, because we have tooling that does so (language
             | servers, CIDER, Calva, Cursive, Conjure...). This means
             | that static typing for the purpose of merely reading the
             | code is a crutch. I'd argue it's also a crutch or training
             | wheels for writing correct code.
             | 
             | You can't run with crutches. You can't corner well with
             | training wheels. Clojure is meant to make the expert nimble
             | and fast. The main thrust of its design is to make
             | experienced devs more productive, like professional tools
             | without novice guide-rails make experienced craftsman more
             | productive.
             | 
             | Rich Hickey gave a talk where he mentioned this idea of
             | guardrails on the highway. He told a story of how we all
             | get in our car, then bump into guardrails all the way to
             | our destination... right? Of course not, we learn to keep
             | the car in our lane of travel, to signal others when we
             | switch, and to blend with other traffic on the way. (Rich
             | was talking about TDD, but it still applies to static type
             | systems, IMHO.) Clojure is that power tool without all the
             | novice presets. It's the automobile we keep away from the
             | rails when we drive it.
             | 
             | Mutable state is arguably responsible for far more defects
             | shipped than type errors. Mutability is only a thing
             | because hardware constraints required reuse of memory
             | locations instead of allowing for persistent data
             | structures. Thankfully, for "situated" applications that
             | start and operate for extended periods, those constraints
             | aren't so tight.
             | 
             | If you have to choose between immutable data and static
             | types choose immutable data. But why not both? We can have
             | all our luxuries, right? Because you have to spend so much
             | more time proving things to the compiler, you have so much
             | more syntax to manage. More code and more syntax for the
             | same problem is almost always worse. I'll take Clojure.
        
               | AnimalMuppet wrote:
               | > There are studies that estimate that the kind of bugs
               | shipped to production that strong static types help
               | prevent account for only 2% of defects. The rest are
               | things like off-by-one errors, design errors, and
               | incorrect logic.
               | 
               | If you've got a reference, I'd be interested. (Not saying
               | you're wrong...)
               | 
               | > The other thing a static type system can help you with
               | is reading code. But it's primarily an aid to people
               | unfamiliar with the language, or put in more popular
               | parlance a "skills issue."
               | 
               | It's an aid to people who are unfamiliar with the
               | _program_ , who have no idea what the shape of "that
               | thing" is. (Especially, what is the shape of the thing
               | that this function gets called with? For _all possible
               | callers_?)
               | 
               | I've been hired to start working on code bases that have
               | existed for a decade or two. Static, stated types are a
               | life saver. Sure, they may slow you down while you're
               | creating the code. It's easier to not have to explain
               | everything that's in your brain. But when you and your
               | brain leave, and I'm left with a bunch of variables that
               | I have no idea what type they are - what are the maximum
               | set of types that they can be for all paths through all
               | callers - then I _really need_ static types to help me
               | figure out what 's going on.
        
               | slowmovintarget wrote:
               | Or you need a REPL that lets you poke at the living code.
               | It's just different.
        
               | slowmovintarget wrote:
               | On the studies, I believe the results were drawn from
               | this [1] study and followed up here [2]. I seem to recall
               | reading a blog post based on these results, but I could
               | be mistaken.
               | 
               | [1]: A Large-scale Study of Programming Languages and
               | Code Quality in GitHub
               | https://dl.acm.org/doi/10.1145/3126905
               | 
               | [2]: On the Impact of Programming Languages on Code
               | Quality: A Reproduction Study
               | https://dl.acm.org/doi/fullHtml/10.1145/3340571
        
           | synthc wrote:
           | Immutability removes so much accidental complexity, it makes
           | whole classes of mistakes dissapear. I'd also take
           | immutability over types.
           | 
           | Clojure sort of guides you to simplicity, building everything
           | out of functions and simple datastructures has big advantages
           | when testing and reasoning about code.
           | 
           | I do find that in larger code bases, Clojure lack of types
           | causes friction (spec is just a bandaid, not a fix).
           | 
           | There are languages with immutability and types (like
           | Haskell), but these don't have the get-shit-done factor I
           | seek.
        
         | yogthos wrote:
         | I've used Clojure for over a decade and the JVM has never been
         | an issue. The only people I see complaining about the JVM are
         | people who never actually worked with it. Meanwhile, there's
         | zero evidence for the notion that static typing has any impact
         | on code quality. https://danluu.com/empirical-pl/
        
       | jrsj wrote:
       | Elixir is a little less flexible since it doesn't have the JVM
       | interop but for domains where it's a good fit I think it's _even
       | better_ at most of this stuff (and easier to teach people
       | unfamiliar with FP or lisps)
        
       | nbittich wrote:
       | I tried clojure long time ago, honestly what made me give up is
       | when I saw a java stacktrace in place of a proper error message
       | when learning it. Also the repl was slow. The UX sucked, I wonder
       | if they improved that
        
         | jb1991 wrote:
         | The repl isn't slow, what are you referring to?
        
           | ekzy wrote:
           | Probably referring to startup time. Larger apps solve this
           | with the "reloaded" type of workflow
           | (https://www.cognitect.com/blog/2013/06/04/clojure-
           | workflow-r...)
        
         | gleenn wrote:
         | There are no Clojure stacktraces specifically, only JVM/Java
         | ones. Clojure sits closely beside its host so there is no
         | difference. People do complain about stacktraces and they've
         | made some improvements. But they are long because the
         | abstractions run deep and the function you passed in might be
         | on the stack at the very bottom with the actual origination of
         | the cause.
        
         | fiddlerwoaroof wrote:
         | I used to hate JVM stacktraces but they're incredibly useful
         | and I miss them when I'm using other ecosystems these days. The
         | way JVM exceptions do "caused by" when an exception is thrown
         | while handling another exception gives so much more information
         | than other languages. It's also relatively simple to filter out
         | the noise when you want a concise error message: just remove
         | lines that start with a tab.
         | 
         | CIDER (the emacs IDE for Clojure) does a really good job of
         | filtering the stack trace and presenting several views
         | depending on what you care about. L
        
         | kccqzy wrote:
         | Usually there is also an error message together with a stack
         | trace. I like stack traces: they are usually more informative
         | than just an error message. I had lost too much time debugging
         | Haskell exceptions where they by default do not come with any
         | stack traces.
         | 
         | The only thing that really sucked is just the documentation.
         | They are overly concise. You end up relying on non-official
         | sources of documentation.
        
       | ilrwbwrkhv wrote:
       | I run a multi-million dollar business which I started with common
       | lisp. I since moved away to go and then rust but I've been
       | looking at clojure again lately.
       | 
       | For a team that needs to get s** done and has more per employee
       | productivity than Faang combined it's hard to beat the speed with
       | which you can build things when you have the repl and interactive
       | programming.
       | 
       | The jvm while doesn't have great error messages is a fantastic
       | runtime.
        
         | giancarlostoro wrote:
         | > which you can build things when you have the repl and
         | interactive programming.
         | 
         | This is how I use Python to be honest. If I'm unsure of
         | something, I just bust out the REPL.
        
           | ilrwbwrkhv wrote:
           | I know people talk about python being Lisp without brackets,
           | but for example in SBCL and in other lisps like clojure I
           | could just run a larger function, figure out that there is
           | the wrong output, change a tiny function in it, eval that,
           | eval the larger output, get the result. In SBCL there is also
           | the break loop which is just magical.
           | 
           | I do not know how you do that in python without using a
           | debugger and stepping through the code line by line. To be
           | fair I used Python only a little bit almost a decade back.
           | Are things more interactive now?
        
             | zelphirkalt wrote:
             | I think in Python REPL you just have to redefine the whole
             | larger function. I am not aware of a way to access
             | internally bound identifiers, or even modify what values
             | they are bound to.
        
             | codr7 wrote:
             | The condition framework/break loop is one thing I wish more
             | Lisps would copy.
        
         | kubb wrote:
         | I feel like there's a minimum developer quality that's needed
         | when using a language like Clojure, without static typing, and
         | with a wealth of idioms and best practices that need to be
         | followed and libraries that need to be known.
         | 
         | Without it it's a matter of time before the codebase can't be
         | developed anymore and the software doesn't work as intended.
        
           | jb1991 wrote:
           | Yes and actually this happens often that a project is moved
           | to another language because of maintainability, especially
           | when a key person leaves the company.
        
           | lispisok wrote:
           | I would love to see how Clojure's "wealth of idioms and best
           | practices that need to be followed and libraries that need to
           | be known" compare to almost any other popular language.
           | Clojure is by far the simplest most straightforward language
           | I've ever used with very few details and gotcha's that need
           | to be memorized.
        
         | oDot wrote:
         | You should give Gleam a shot. No REPL, but its simplicity,
         | functional-ity and the BEAM lend themselves to the get-shit-
         | done approach
        
           | ilrwbwrkhv wrote:
           | Gleam takes more code to write than rust. Doesn't have a
           | strong enough documentation / ecosystem yet. But I agree the
           | beam VM is very underutilized and underappreciated.
        
           | ndr wrote:
           | Immutable data and REPL is where is at for iteration speed
           | though.
        
         | closeparen wrote:
         | Different meanings of "productive." In a language like Clojure,
         | you could have one engineer rewrite the entire system in a
         | weekend. Which is very valuable if you're an early-stage
         | startup! But you are probably leaving some corporate
         | productivity on the table if you already have the maximum
         | number of people who can coexist in the codebase without
         | interference, and +EV work is still piling up in the backlog.
        
         | agumonkey wrote:
         | Can you describe your stack and workflow ?
        
       | MarkMarine wrote:
       | Learning clojure has improved all of my programming in every
       | language. I'm in love with the simplicity and smallness of it.
       | Rich said one of the reasons he built it was he was programming
       | like this already (pure functions acting on data) but the
       | languages he was using didn't support it well. There is a lot to
       | be learned and applied even if you can't use clojure at work
       | every day.
        
       | ampunix1337 wrote:
       | Idk ... it feels Clojure stalled since Nubank bought Hickeys
       | company. Worst thing: spec is still in alpha !! I put so much on
       | this ... but nothing really happened since ... idk 8 years?
        
         | ekzy wrote:
         | Call it "stalled" if you like, it's stable and it's pure joy. I
         | can just get stuff done with Clojure. And things that may seem
         | inactive, like that lib that you need that hasn't had a commit
         | in 8 years, turns out that it just works and doesn't need to
         | change. This is commonplace in Clojure.
         | 
         | Spec is still alpha and I'm not sure it will evolve more or if
         | it'll be something completely different. At least they're not
         | pushing you down the wrong path. Use/look at Malli instead of
         | spec.
        
         | yogthos wrote:
         | Spec isn't really essential to Clojure, and most people use
         | Malli nowadays which is very actively developed
         | https://github.com/metosin/malli
         | 
         | I see the fact that there isn't much happening with the
         | language as a positive myself. I want the core language to be
         | small and stable. The big difference with Clojure and most
         | languages is that it makes it far easier to implement new
         | semantics in user space. It has a powerful macro system and new
         | ideas can be expressed using libraries instead of having to be
         | baked into the core language itself.
         | 
         | Most language grow through accretion as usage patterns change
         | over time. New end up features end up getting bolted on to
         | facilitate that, and the language keeps growing. The problem
         | here is that the scope of things people have to know keeps
         | growing as a result.
         | 
         | Meanwhile, Clojure managed to stay small and focused, while
         | different kinds of ideas are expressed using libraries. When a
         | new idea comes along people can just use a new library, and
         | they don't have to learn about all the previous libraries that
         | worked differently. I think this is a huge benefit from user
         | perspective.
        
         | slowmovintarget wrote:
         | But have you seen _flow_? I don 't think it's stalled at all,
         | and Nubank seems to have become an enabler to the ecosystem.
         | 
         | I mean, Datomic is free to use!
         | 
         | [core.async.flow]:
         | https://github.com/clojure/core.async/commit/03b97e0b3e0ec32...
        
         | lukev wrote:
         | I don't know what you're talking about, 2 new versions of
         | Clojure have come out since then, both of which have more
         | substantive changes than the previous couple versions.
        
       | codr7 wrote:
       | Tried to love Clojure, but found it to opinionated as a daily
       | driver for me.
       | 
       | Sometimes I just need to get some code running to see a result,
       | which is my main use case for Lisp.
       | 
       | I used to default to Common Lisp, but it needs a lot of
       | scaffolding to become ergonomic, and even then it has too many
       | quirks to be really enjoyable for me.
       | 
       | So I started designing my own:
       | 
       | https://github.com/codr7/eli
        
         | thom wrote:
         | What wall did you hit? I can jump into a Clojure REPL without
         | needing a project or even any files.
        
         | cellularmitosis wrote:
         | Macros being supported via quoted arguments is clever
        
       | viccis wrote:
       | I like Clojure well enough, but it feels like every single time I
       | see it mentioned now is an write up trying to justify using it.
        
       | phtrivier wrote:
       | The part about the "stability" is a bit surprising - in my
       | experience, I try playing with clojure about once a year, and
       | every time, everything is different (I mean, I had to go through
       | classpathes, then lein, then boot, then deps.edn - what is the
       | current way to "try and run a program" du jour ?)
       | 
       | Also, is running your "hello world" still going to be incredibly
       | slow, or has something changed in the core system (I know I'm
       | supposed to fix that with graails. Or is it babashka ? Or
       | something else, I suppose.)
       | 
       | It's really sad, because i just love the language. Reading about
       | clojure is a pleasure. Trying to write anything has always been a
       | blocker to me, though. Maybe that's the true "immutable" nature
       | of the language ?
        
         | cschep wrote:
         | While clojure has gained (accreted) more options of ways to run
         | things, every single one of the ways you mentioned still work!
         | It's extremely stable in this regard. Nothing was taken away
         | because there is a new hotness. Sure, things were added. Why is
         | that bad at all?
        
       | newlisp wrote:
       | Using Clojure without Datomic can be frustrating since you feel
       | like you lose some of the language's value, as you likely want to
       | extend its philosophy and style to the database as well. Of
       | course, Hickey probably knew this when he started planning
       | Clojure, which is why he also created Datomic. However, Datomic
       | can be a hard pill to swallow
        
       | dustingetz wrote:
       | Why Clojure = for Datomic, Rama, Electric and Missionary. No need
       | for long blog post - this stack screams if your app fits within
       | its intended operational margins - enterprise cloud information
       | systems and rich interactive web products.
        
       | d_t_w wrote:
       | My co-founder uses the phrase minimal-viable-company for maximum-
       | viable-product.
       | 
       | We bootstrapped for 5 years to well over $1M+ ARR before recently
       | closing a seed round[1], Clojure played a large part in our
       | ability to deliver as a small team. Also in our general happiness
       | as programmers, it is a nice language to work in.
       | 
       | We will grow our Clojure core product team over the next couple
       | of years, but mostly the funding round is about balancing our
       | business to keep up with our product delivery.
       | 
       | Clojure has been very good to me (I had 15 years on the JVM prior
       | to moving to clj/cljs in 2013-ish). YMMV.
       | 
       | [1] https://factorhouse.io/blog/articles/from-bootstrap-to-
       | black...
        
       ___________________________________________________________________
       (page generated 2025-02-23 23:00 UTC)