[HN Gopher] Why Clojure?
       ___________________________________________________________________
        
       Why Clojure?
        
       Author : jgrodziski
       Score  : 292 points
       Date   : 2025-02-22 09:44 UTC (2 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.
        
               | Capricorn2481 wrote:
               | I think their point is, even with the REPL, it takes time
               | to track down every spot that function might be called
               | and figure out what was passed to it. A type is very easy
               | to see localized on the function.
        
               | iLemming wrote:
               | > A type is very easy to see localized on the function.
               | 
               | "You Keep Using That Word, I Do Not Think It Means What
               | You Think It Means"...
               | 
               | When you say "types," can you please give a concrete
               | example of what languages you're talking about? Whenever
               | someone talks about Clojure from type theory talking
               | points, they make it sound like it's completely untyped
               | or weakly typed. Clojure has its own type systems, and
               | you can express things in them that are far more
               | difficult to do in some other languages, even with static
               | types. It is also a strongly typed language, and in
               | practice, I feel far more confident about our Clojure
               | code than anything written in TS or Java.
               | 
               | Sure, static type systems have their value, and some of
               | them are really nice. In practice though, whenever I have
               | to jump in to deal with Java, Typescript, or even Rust
               | code - there's so much seemingly unnecessary fluff, and I
               | don't feel the practical worth of dealing with types - it
               | almost always feels taxing. Haskell/OCaml is a different
               | story - I can buy that one. But realistically, getting to
               | the point of writing practical software in Haskell is an
               | incredibly bumpy road, and (relatively) few programmers
               | successfully achieve good milestones on it.
        
               | Capricorn2481 wrote:
               | I use Clojure. I'm aware it's strongly typed. I never
               | said it wasn't, actually. You might want to reread my
               | comment.
               | 
               | But I can't expect most codebases to use spec or malli.
               | The comment I replied to said that's what the REPL is
               | for. A REPL, while helpful for a lot of things, will not
               | tell you about an argument faster than a type annotation.
        
               | 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/
        
           | huahaiy wrote:
           | For someone who needs static typing, Clojure give them
           | defprotocol, deftype and defrecord.
           | 
           | Interestingly, most of the low level libraries in the Clojure
           | ecosystem are programmed that way. If you open up the code of
           | many popular Clojure libraries, you see defprotocol
           | everywhere.
           | 
           | So really, Clojure does both: dynamic typing for application
           | programming, mostly static typing for infrastructure library
           | code. As they should be.
           | 
           | This tired argument of "Clojure bad for dynamic typing" just
           | doesn't hold water. Keep repeating it is a sign of lack of
           | critical thinking.
        
             | yogthos wrote:
             | I'd argue defprotocol, deftype, and defrecord provide much
             | weaker guarantees than a type system. Dtuff like
             | defprotocol tends to serve a similar use case to using an
             | interface in Java. You specify the signatures for the
             | functions, and then a concrete implementation can be
             | provided using a library. Ring servers are a good example
             | of this where you can easily plug different server
             | implementations by just swapping a library.
             | 
             | There is Typed Clojure https://typedclojure.org/ for people
             | who want actual static typing, but the fact that it never
             | caught on suggests this wasn't a real pain point for most
             | people using Clojure.
             | 
             | As other people mentioned, immutability tend to be a more
             | important feature than static types because it makes it
             | easy to write code that's referentially transparent. You
             | can structure your whole application as a series of small
             | components that can be reasoned about in isolation.
        
               | huahaiy wrote:
               | Nobody would argue that Java is not statically typed.
               | That's my point. Clojure offers the same as what Java
               | offers.
               | 
               | If you write code in a defprotocol everywhere style, as
               | many Clojure libraries do, your code won't compile if you
               | got the types wrong. The same as Java. How's that not
               | static typing? Which part of that is weaker?
               | 
               | So what exactly this "Clojure dynamic typing" nonsense is
               | about, I fail to see.
               | 
               | Automatically inferred type system is not the same thing
               | as static typing. Typed Clojure is the former. Typed
               | Clojure did not catch on, but static typing style of
               | Clojure did, as many Clojure libraries do exactly that:
               | internally, defprotocal everywhere, externally, some
               | Clojure functions to give the illusion of normal Clojure
               | code. BTW, that's the style how Clojure itself is written
               | in as well.
        
               | mrkeen wrote:
               | > If you write code in a defprotocol everywhere style, as
               | many Clojure libraries do, your code won't compile if you
               | got the types wrong. The same as Java. How's that not
               | static typing? Which part of that is weaker? > So what
               | exactly this "Clojure dynamic typing" nonsense is about,
               | I fail to see.
               | 
               | No-one has the time to learn all these languages, so for
               | those of us not in the know, the most generous we can be
               | is to take these praise articles at face value. And these
               | articles are typically 'dynamic good', 'static bad'.
               | 
               | From the article:                 they insist on a
               | statically typed worldview leading to parochial,
               | snowflake APIs that defy abstraction and higher level
               | manipulation, or both.
               | 
               | So I guess the user base for this language is those
               | developers who think dynamic is better than static, and
               | go for (as-static-as-Java) Closure.
        
               | ugaibugai wrote:
               | The part of code not compiling got me interested. Do you
               | happen to have an example or tutorial about this?
        
               | yogthos wrote:
               | That's not quite true though. Java tracks types in the
               | signatures of the functions, defprotocol does not. If I
               | make a protocol and then pass a wrong type as a parameter
               | to it then I'll get a runtime error. It's not going to
               | tell me that I passed in a wrong type at compile time.
               | 
               | I find using defprotocol in Clojure tends to be an
               | antipattern because it just makes code harder to read by
               | introducing indirection. The libraries using defprotocol
               | use it to solve a specific problem of creating a contract
               | for how the API looks.
        
               | huahaiy wrote:
               | Then you are not writing in defprotocol everywhere style.
               | The keyword is everywhere. All the domain objects are
               | deftype or defrecord. Try that. It is the same as Java,
               | basically.
               | 
               | It is not an anti pattern, it is the way most low level
               | libraries and clojure itself are written.
               | 
               | Clojure is a tool, not a cult. This core team worship is
               | turning people away. The core team made plenty of
               | mistakes, and got called out, rightfully.
        
               | yogthos wrote:
               | Even if you did, that wouldn't solve the problem because
               | many checks are still done at runtime. Also, if you
               | started doing that then you might as well just write Java
               | at that point. I've worked on code bases structured in
               | this way and it's absolutely terrible to work with. For
               | one, protocols completely break any sort of REPL driven
               | development.
               | 
               | Most libraries are absolutely not written in this way
               | either. Please point me to a single library that's
               | actually written in the style you describe. The use of
               | protocols in actual popular libraries like Ring tends to
               | be minimal.
               | 
               | The reality is that dynamic typing has never been a real
               | problem in Clojure. I've worked with the language almost
               | exclusively for over a decade now, and I maintain a
               | number of popular libraries, like Selmer, with millions
               | of users.
        
               | huahaiy wrote:
               | That has nothing to do with types. You are now talking
               | about when a compiler is run.
               | 
               | Clojure gives you the option to run the compiler at
               | runtime, so that's what people normally do. However, you
               | can also run the compiler at compile time. Right?
               | 
               | For people who want type checking, they can opt to write
               | Clojure in this defprotocol everywhere style, and turn on
               | AOT. Then they basically get the same thing as what Java
               | gives them.
               | 
               | As to example of libraries that are defprotocols
               | everywhere, you should look at any of the low level
               | performance minded libraries in the Clojure ecosystem,
               | they are either written in this defprotocols everywhere
               | style, such as nippy, neanderthal, dtype-next, and so on,
               | or mostly in Java, such as http-kit, fast-edn, etc. I
               | noticed this phenomenon, because my own libraries,
               | editscript and datalevin, are written in this way. I take
               | comfort that my fellow performance minded library authors
               | are doing the same. Finally, isn't Clojurescript entirely
               | driven by protocols?
               | 
               | So really, there are two kind of Clojure programmers. One
               | type writes application code or high level libraries, and
               | they write normal Clojure code all the time. However,
               | there are also those who write primarily low level
               | library code, which are used by the first camp, and their
               | code is full of defprotocol and deftypes. So defprotocol
               | everywhere is not anti-pattern. It's anti-pattern only in
               | the mind of the first camp of programmers, and that's a
               | narrow minded way of looking at things. Even the first
               | version of Clojure Programming book by the core team
               | members, are written in a way that's full of defrecord.
               | Remember?
               | 
               | This "everything is a map" orthodoxy is turning people
               | away from Clojure. Just let people write the code that
               | suits their own needs. We can use more people who are
               | pragmatic instead of dogmatic in the Clojure world. If
               | you trust Rich Hickey's judgment, then you should trust
               | him put in the features Clojure has for good reasons.
               | Macros and protocols are part of the Clojure language,
               | and you should be using them when the use case calls for
               | them. Stop the "anti-pattern" nonsense.
        
         | iLemming wrote:
         | Clojure is strongly typed. That manifests in, for example, when
         | Clojurescript emits compiled Javascript. Surprisingly, often it
         | emits safer Javascript than Typescript ever could with all its
         | static types. Typescript's type system exists only at compile
         | time for development and static analysis. When compiled to
         | Javascript, all type annotations and interfaces are removed,
         | leaving code that runs dynamically at runtime, meanwhile
         | Clojure retains its strongly typed guarantees.
         | 
         | Coders often accept the status-quo of things - "So what that we
         | can't easily upgrade our dependencies in our Node/Ruby/Python
         | project - it's a known thing, we just have to deal with it...";
         | "Of course our builds take 90 minutes, that's normal for a big
         | project"; "We need complex state management like Redux"; "Code
         | must be recompiled after every change"; "Testing requires
         | mocking everything", "Type safety prevents runtime bugs"; etc.
         | 
         | Yet, when it comes to actual work, not some cheap talking
         | points but real, practical scenarios - there aren't many other
         | tools that can beat Clojure for robustness, pragmatism, and
         | speed of building things with it.
         | 
         | Most experienced Clojuristas are incredibly knowledgeable,
         | skilled, and seasoned programmers, architects, and system
         | designers who are passionate about their craft, using tools,
         | techniques and patterns that enable them to perfect it while
         | remaining pragmatic and grounded. But hey, don't blindly trust
         | my word, go see for yourself - open ClojureTV YT channel, watch
         | their presentations and draw your own conclusions.
        
           | KingMob wrote:
           | Not the OP, but usually, when people talk about type safety,
           | they're referring to some flavor of static typing, not strong
           | typing.
           | 
           | Very few languages still in use in the modern era are still
           | weakly-typed.
           | 
           | My personal take is that while a lot of type systems can be
           | overblown, nil-punning is not a sufficient substitute for
           | optional/maybe types.
        
       | 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...)
        
             | jb1991 wrote:
             | I would often leave repls running for days so it never
             | seemed to matter.
        
         | 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.
        
               | int_19h wrote:
               | For starters, those identifiers aren't bound until the
               | function actually runs.
        
             | codr7 wrote:
             | The condition framework/break loop is one thing I wish more
             | Lisps would copy.
        
               | ilrwbwrkhv wrote:
               | Thats the one thing I miss in Clojure from CL. Although
               | technically due to Clojure' immutability you have to do
               | the same number of changes. But just dropping into the
               | break loop, updating, continuing is just magic.
        
               | codr7 wrote:
               | Makes the REPL feel a lot more alive and interactive,
               | much like a SmallTalk IDE.
        
             | sodapopcan wrote:
             | > I know people talk about python being Lisp without
             | brackets
             | 
             | What on earth?? Who are these people, this is the first
             | I've heard of this and am having trouble understanding what
             | the argument could be. Like, basically all languages get
             | transformed to an AST as part of the compile step soooo I
             | guess any language is sort of a lisp.
        
               | jodrellblank wrote:
               | Peter Norvig: https://www.norvig.com/python-lisp.html -
               | "Basically, Python can be seen as a dialect of Lisp with
               | "traditional" syntax (what Lisp people call "infix" or
               | "m-lisp" syntax). One message on comp.lang.python said "I
               | never understood why LISP was a good idea until I started
               | playing with python." Python supports all of Lisp's
               | essential features except macros, and you don't miss
               | macros all that much because it does have eval, and
               | operator overloading, and regular expression parsing, so
               | some--but not all--of the use cases for macros are
               | covered."
               | 
               | "Take a Lisp program, indent it properly, and delete the
               | opening parens at the start of lines and their matching
               | close parens, and you end up with something that looks
               | rather like a Python program."
               | 
               | also Peter Norvig on HN:
               | https://news.ycombinator.com/item?id=1803815
        
         | 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.
        
             | travisgriggs wrote:
             | I can appreciate that. I'm on a journey this last year or
             | so with Elixir, which also has an elevator pitch of
             | "consistency" and "simplicity", true to a couple of
             | defining principles, rather than hodge podge of committee
             | like language initiatives.
             | 
             | But does it really matter now days? If you're doing
             | anything web oriented, you don't get to abstract the hot
             | mess that is web programming away. You still have to learn
             | a ton of nuanced stacks, many couched in idioms that were
             | established decades ago, and perservere today, wrapped in
             | layers of whatever.
        
             | kubb wrote:
             | I think Go, for all its flaws, is an example of a language
             | where mediocre developers can be more successful.
             | 
             | Java would be another.
        
           | ilrwbwrkhv wrote:
           | well i agree you need developers who are on the senior side
           | but thinking about data and pipelines, multi methods etc,
           | makes for a quite extensible, large, applications.
           | 
           | the fact that because of the repl the happy path is always
           | tested while being built and with clojure spec you can secure
           | the edges, it is quite scalable.
           | 
           | i love static typing and rust in general but with web
           | applications, the problem space is really a distributed
           | concurrency problem of dynamic data. and clojure is basically
           | tailor made for that.
        
           | rpcope1 wrote:
           | You could replace Clojure with Python or Perl, and this Would
           | honestly be even more true.
        
         | 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.
        
             | MarkMarine wrote:
             | I see gleam as a sweet spot, the type system I'd prefer to
             | be writing (rust's sensible one) and I never have to fight
             | with the borrow checker
        
             | tasuki wrote:
             | > Gleam takes more code to write than rust.
             | 
             | Do you have some source for that? Perhaps an example?
        
               | ilrwbwrkhv wrote:
               | No. Take that with a grain of salt. I did some large file
               | reading in the past and gleam doesn't have a good
               | abstraction for that yet whereas in rust it was
               | straightforward. Simplifile basically reads the whole
               | file into memory.
        
               | cess11 wrote:
               | They've added https://hexdocs.pm/file_streams/0.6.0/ for
               | this purpose.
               | 
               | There's a bit of ceremony but similar to how you can
               | interface with Java libraries from Clojure you can pull
               | in Erlang when Gleam isn't enough.
               | 
               | You can do some code shortening with use,
               | https://erikarow.land/notes/using-use-gleam, but it will
               | likely always be rather chatty and won't support
               | metaprogramming: https://lpil.uk/blog/how-to-add-
               | metaprogramming-to-gleam/
        
           | ndr wrote:
           | Immutable data and REPL is where is at for iteration speed
           | though.
        
         | agumonkey wrote:
         | Can you describe your stack and workflow ?
        
         | anonzzzies wrote:
         | Did you move from CL because of hiring or another reason? I
         | cannot imagine leaving CL and if I had to, I would go for abcl
         | and then add clojure. Depending on the business that is of
         | course. As long as I don't need to build a 1000s person tech
         | team, I would not move; it's just far faster until you get to a
         | scale where processes take over everything.
        
           | ilrwbwrkhv wrote:
           | Hiring. And honestly the docs and stuff look really dated and
           | I understand why people are a bit put off. At some point you
           | have to modernize the look and feel of the ecosystem. The
           | docs are really detailed though and if it was just me and a
           | few others I would have gone to CL in a heartbeat.
        
             | anonzzzies wrote:
             | Yes, they look dated but most things are just so incredibly
             | stable, robust, easy to work with once you are in.
             | 
             | One of my pet peeves on github is with modern ecosystems
             | that people ask after 1 week of no commits 'is this project
             | dead'; we use rocksolid well documented and robust
             | libraries that have basically not been updated for a
             | decade; apparently you _dont_ need to change the api every
             | 2 days completely and introduce breaking changing in minor
             | versions of libraries where the actual thing they have
             | solved hasn 't changed since the dawn of computers
             | themselves... Like is the normal in npm libs for github
             | star vying.
             | 
             | And the supposed lack of libraries; sure it happens, but
             | more often it is so easy to roll (99% of npms) that in CL
             | no one would use the CL lib if their was one; faster to
             | roll than search for one.
             | 
             | I agree with the modernisation steps though: need to bring
             | together fairly recent enough _industry_ users and scan
             | their code base for which common lisp functions and libs
             | are used (as for as I see, most practical people use a
             | subset and don 't often go look for different ways to do
             | something they might be buried in hyperspec somewhere) and
             | distill that down to a Industry Common Lisp 'spec' and
             | modernise everything related to that.
        
         | wooque wrote:
         | Why did you move away from go? I don't use it, but seems like
         | productive language, being simple, fast to compile and
         | performant.
        
           | ilrwbwrkhv wrote:
           | So go has runtime failures due to null pointers. When dealing
           | with a bunch of json and dynamic data, I don't need to deal
           | with null pointers in 2025.
        
           | MarkMarine wrote:
           | You can make really shitty code in any language, and the go
           | community's patterns around essentially brute forcing things
           | (or code generation when that fails, which is horrible. Time
           | to learn another custom DSL just to have an abstraction)
           | rather than have good abstractions built into the language...
           | it becomes painful if you've worked in a language with a
           | better systems.
           | 
           | Pointers and null values are inescapable in go, and people
           | treat them worse than they do in C. Generics are too limited
           | (I can't define a scala flatmap like function) And I can't
           | make data immutable or control access in any fine grained way
           | in go. Compile time in my go monorepo is minutes now. Someone
           | added a bunch of go lint rules.
        
           | valenterry wrote:
           | > being simple
           | 
           | Being simple is not a good thing. A simple language means
           | that the programs become complex and hence complicated. The
           | advantage is that it's easy to get up to speed and to write
           | greenfield code though.
        
       | 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.
        
         | DeathArrow wrote:
         | >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.
         | 
         | But he could have been using F#, OCaml, Haskell. So it might
         | not be just about pure functions and immutable data.
        
           | yogsototh wrote:
           | For being an Haskell and Clojure dev. Data manipulation in
           | Clojure requires a mind shift coming from Haskell. But it
           | feels a lot more straightforward in Clojure. Even if `lens`
           | is incredible. This is like Haskell lenses was were included
           | in the core language if you want. Of course, not type-safe.
           | This is just that, solving problems in Haskell or in Clojure
           | does not really require the same approach. But both ways are
           | delightful. And personally, Clojure has always felt more
           | natural, even though, I also love the Haskell approach.
        
       | 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.
        
           | tombert wrote:
           | There are things in the core language that are still kind of
           | bullshit. The thing that gives me the most headaches is how
           | annoying it is to use Java libraries that have the lambda
           | syntax.
           | 
           | You can't just pass in a Clojure `fn` into a Java lambda
           | function. You have to `reify` the interface and implement the
           | single method. It's annoying and verbose and frustratingly
           | the equivalent code is considerably cleaner in Java as a
           | result.
           | 
           | I know that this is a product of how Java implemented lambdas
           | by having interfaces with a single method, and I'm not saying
           | that it would be trivial to add into Clojure, but I don't
           | think it's impossible and I think people have been
           | complaining about this for more than a decade now.
           | 
           | So while I love Clojure, it's probably my favorite language,
           | I do get a little annoyed when people act like it's "stable"
           | because there's nothing to fix.
        
             | mattmein wrote:
             | I think that particular issue was addressed in the recent
             | Clojure release
             | [https://clojure.org/news/2024/09/05/clojure-1-12-0]
             | ("Clojure developers can now invoke Java methods taking
             | functional interfaces by passing functions with matching
             | arity.")
        
               | tombert wrote:
               | Looks like you're right! I stand corrected, it's
               | admittedly been a few months since I've touched Clojure.
        
               | newlisp wrote:
               | You were not wrong though, Java 8 was released in 2014,
               | so it only took them ~10 years ;)
        
               | tombert wrote:
               | Yeah, and most of my professional Clojure experience was
               | from 2018 to 2021, and a few personal projects in 2022
               | and 2023, and that lack of support for the functional
               | APIs really annoyed me; I was writing a Kafka Streams
               | application, which uses lots of lambdas, and it annoyed
               | me enough to rewrite it with vanilla Java.
               | 
               | I'm sure it's a difficult thing to implement, so I'm a
               | little forgiving, but considering that Java interop is
               | one of the biggest selling points for Clojure I do think
               | it's fair to criticize a bad experience with it.
               | 
               | I need to play with the newer stuff though; the linked
               | changes seem cool as hell.
        
           | KingMob wrote:
           | > At least they're not pushing you down the wrong path
           | 
           | No, but the release of spec single-handedly killed Schema, a
           | more mature contract lib.
           | 
           | Then spec stagnated, because the core team didn't want to
           | work on it, but as a core team library, nobody else can work
           | on it, either.
           | 
           | Thus was born Malli, because people got tired of waiting.
        
         | 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...
        
           | masijo wrote:
           | I really don't understand what flow is and what problem it
           | solves. I've read the commit comments and some posts but I
           | still don't get it.
        
             | slowmovintarget wrote:
             | Here's Rich Hickey's explanation if it helps: https://www.r
             | eddit.com/r/Clojure/comments/1i27n1k/rich_intro...
             | 
             | His comment walks you through what it's for. The basics:
             | configure your flow of data from producer to queue to
             | consumer and so on as data, in one place.
        
         | 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.
        
           | codr7 wrote:
           | The opinions on data and programming in general-wall.
           | 
           | Not bad ideas, just not the kind I like shoved down my
           | throat.
        
         | cellularmitosis wrote:
         | Macros being supported via quoted arguments is clever
        
           | codr7 wrote:
           | Thank you, I'm very pleased with that detail :)
        
       | 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.
        
         | iLemming wrote:
         | > justify using it
         | 
         | Justify using it against what? Can you name a single other
         | language that does things better than Clojure? Not from your
         | "point of values," but try seeing it from my position. Is there
         | anything that can replace Clojure for me? I love the dynamism,
         | malleability of the language - the flow; writing Clojure
         | programs for me feels like playing a video game - it's plenty
         | of fun. I don't get the same kicks from literally any other
         | "mainstream-ish" language that's being used today. I like
         | Common Lisp, but I have never had any practical, large
         | opportunities to use it seriously, and there are things that I
         | love in Clojure that I'm sure I'll miss in CL. I like Haskell,
         | but it's even less practical (for me).
         | 
         | In my view, there isn't a single language that respects good
         | ideas carried in Clojure and does them in a better or at least
         | pragmatically viable fashion - I've evaluated Elixir, OCaml,
         | Rust and some other choices. I am excited about Jank, can't
         | wait for it to hit the first production-ready release. But
         | today, nothing is more joyful for me to use than
         | Clojure/Clojurescript.
        
           | kunley wrote:
           | Haha, it is "against what" that you have added by yourself.
           | And that's exactly the issue with this kind of posts and
           | comments: going right away into either a very defensive mode
           | or a fight mode.
        
           | cmbothwell wrote:
           | What was it about Elixir that you found dissatisfactory? I am
           | currently evaluating Clojure vs. Elixir for a new project.
        
             | innocentoldguy wrote:
             | I spent a lot of time objectively evaluating languages for
             | a new project I built several years ago. Elixir won out. It
             | has now been 12 years and I still believe Elixir was the
             | right choice for the following reasons (this list is not
             | exhaustive):
             | 
             | BEAM handles concurrency better than the JVM.
             | 
             | Elixir threads are implemented using private memory where
             | Clojure uses public memory.
             | 
             | Mix is superior to Clojure's tooling.
             | 
             | Elixir is easier to learn and write.
             | 
             | OTP is fantastic.
             | 
             | Phoenix is an excellent web framework.
        
               | worthless-trash wrote:
               | If you want lisp on beam there is always lfe .
        
         | dankwizard wrote:
         | The kids these days throw the word "copium" around and that's
         | exactly what it is.
         | 
         | There is a lot of elitism around Clojure and all of them are
         | looking to throw down. Even your comment has already garnered 1
         | of them out of the shadows.
        
           | rads wrote:
           | I'm curious, how did you form this opinion? Did you have a
           | bad experience with Clojure yourself?
        
         | delegate wrote:
         | Are we reading the same articles ?
         | 
         | I see articles (like the one above) where people are sharing
         | their excellent experience using the language as has been my
         | experience over the years of using it.
         | 
         | A justification would be 'we hate this ugly thing, but we use
         | it because it's cool', but that's not what I've been reading..
        
       | 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?
        
           | Lyngbakr wrote:
           | Personally, I prefer it when there is a solid default tool
           | chain for a language rather than having to choose from one of
           | several. That way, I know pretty much what to expect when I
           | open _any_ project in that language. I feel like this is one
           | of the few places where Clojure dropped the ball and that
           | deps.edn should 've been there from the get-go.
        
             | th0ma5 wrote:
             | What language ecosystem does this right?
        
               | riwsky wrote:
               | Go
        
               | asa400 wrote:
               | Both Rust and Elixir get this right. I have used both in
               | anger, for money, to ship real stuff, and while neither
               | is perfect, they are both great.
               | 
               | To a first an approximation, every Rust project uses
               | Cargo and every Elixir project uses Mix, and they are
               | both first-party tools so they have a level of stability,
               | approachability, and ubiquity that comes with being tied
               | to the language. I'd kill for Clojure to have something
               | half as good as Cargo or Mix and have it be the only
               | build tool, but that ship has sailed.
        
         | saghm wrote:
         | I've always heard that the JVM[0] in general is considered to
         | have a fairly high startup time compared to other common
         | compiled language targets; is Clojure especially bad in this
         | regard, or is this something that's frustrating coming from
         | outside the JVM ecosystem that just adds additional friction
         | when you're already trying to look into using new language?
         | 
         | [0] Not sure what the correct term is here, but I mean the
         | official default one; I know there are other implementations,
         | and my vague recollection is that there's at least one other
         | one that's either sponsored or maybe even fully developed by
         | Oracle, and that the OpenJDK version is the "canonical" non-
         | enterprise one now anyhow, so saying " first party" feels like
         | it might add more ambiguity than it would resolve
        
           | Capricorn2481 wrote:
           | The JVM has bad start up time in the context of milliseconds,
           | but Clojures slow start up is in a different league. It loads
           | a bunch of classes and it can take a full second.
           | 
           | But you're also not recompiling on code change. You're just
           | reloading a function in the REPL. So you only have to load
           | once and then your dev cycle is painless. But the startup
           | time is bad for things like serverless functions unless you
           | use something like GraalVM.
        
           | hlship wrote:
           | ~ > time bb -e '(println "Hello World")' Hello World bb -e
           | '(println "Hello World")' 0.01s user 0.03s system 18% cpu
           | 0.212 total
           | 
           | bb is Babashka: a pre-compiled (using Graal), interpreted,
           | scripting language version of Clojure.
           | 
           | In terms of realistic work:
           | 
           | ~/workspaces/github/pedestal/tests > time clj -X:test {:in
           | user/eval2321, :line 13, :thread "main", :dev-mode? false}
           | 
           | Running tests in #{"test"}
           | 
           | ...
           | 
           | Testing io.pedestal.test-test
           | 
           | Ran 391 tests containing 1180 assertions. 0 failures, 0
           | errors. clj -X:test 30.15s user 2.04s system 203% cpu 15.838
           | total ~/workspaces/github/pedestal/tests > java -version
           | openjdk version "23.0.2" 2025-01-21 OpenJDK Runtime
           | Environment Corretto-23.0.2.7.1 (build 23.0.2+7-FR) OpenJDK
           | 64-Bit Server VM Corretto-23.0.2.7.1 (build 23.0.2+7-FR,
           | mixed mode, sharing)
           | 
           | That's on my Intel MacBook Pro. Pedestal's test suite loads a
           | good amount of Java classes and Clojure namespaces.
           | 
           | To make things faster, there's ahead-of-time compilation
           | (which basically captures the read-eval-create-bytecode part
           | of loading a Clojure namespace as Java .class files that can
           | be packaged into your app).
        
         | jayceedenton wrote:
         | 10+ years ago Clojure had a fantastic introductory experience.
         | lein new and away you go. lein was so good and effective, for
         | both tiny hello world projects and real production apps.
         | 
         | The experience has gotten worse and worse now for a decade. The
         | core team have continued to take things in a worse direction
         | (supported by a small group of fanboys) and most newcomers are
         | now completely baffled by the tooling.
        
           | hlship wrote:
           | The cli/deps.edn tooling is _different_ from Leiningen, and
           | far, far less complicated IMO. I 've written a good number of
           | Leiningen plugins and it was always brutal to get anything to
           | work properly, especially in combination with other plugins.
           | 
           | Leiningen attempts to be everything to everyone in terms of
           | building, testing, and packaging Clojure code. It's Clojure's
           | version of Maven.
           | 
           | cli/deps.edn effectively reduces things down to a) what
           | should be on the classpath and b) what should get executed.
           | Working inside an IDE? You just want it to download the
           | dependencies and build a classpath. Running nREPL? Add that
           | to the classpath, and set the starting namespace to start
           | nREPL. Packaging an application? Run dependencies that do
           | that work, based on the clojure.tools.build library.
           | 
           | I was there myself; I used Leiningen and didn't take the time
           | to figure out deps.edn --- until I did, saw the light, and
           | converted all of Walmart's projects to use deps.edn, which
           | greatly sped up our build and improved our dev experience.
        
             | KingMob wrote:
             | tools.deps is less complicated mostly because it just flat-
             | out does much less. To mimic everything lein can do
             | required adopting half a dozen other libs and writing your
             | own build scripts.
             | 
             | It's better now, but people are pretty uncritical of the
             | core team, and adopted tools.deps before its surrounding
             | ecosystem was ready to fully replace lein.
             | 
             | The upshot was, everyone got to rebuild the wheel for a
             | couple years. And I say this as someone who once lost a
             | week debugging a subtle lein/maven classpath AOT bug.
        
           | huahaiy wrote:
           | You can still do lein new and away you go, today. That still
           | works.
           | 
           | Many people still use lein for new projects, especially for
           | larger ones. For small on-off thing, clojure command line is
           | more convenient. So it is a good thing to have more choices.
        
           | phtrivier wrote:
           | Also, today, half the docs you find around are about lein,
           | half are about tools.deps, and no one ever gets the full
           | definition because they assume you know your way around.
           | :shrug:, I guess ?
        
         | jwr wrote:
         | I have been building my (money-earning SaaS) app with leiningen
         | for 10 years now. There is no "du jour", unless you choose to
         | be "du jour".
         | 
         | If you care about startup time (I don't, my app starts only
         | once), you can use babashka for scripting.
        
         | eduction wrote:
         | > everything is different... I had to go through classpathes,
         | then lein, then boot, then deps.edn
         | 
         | All that stuff still works and I don't think any of them broke
         | their APIs? A lot of people still use lein for example.
         | 
         | You're talking about new choices coming along, which is a good
         | thing.
         | 
         | Of all the ones you listed, only one is a product of the core
         | team, so it's not like there has even been "change" on any
         | official level.
         | 
         | If your mindset is, "I need to be on the latest hot thing"
         | that's about you, not Clojure. You're allowed to keep building
         | your projects using any of those tools, they still have the
         | same capabilities.
        
           | phtrivier wrote:
           | > If your mindset is, "I need to be on the latest hot thing"
           | that's about you, not Clojure. You're allowed to keep
           | building your projects using any of those tools, they still
           | have the same capabilities.
           | 
           | Beware here: it might sound natural to you, but many (and I
           | many _many_) people are working on stacks where "there has
           | been no update to this lib for 6 months" means "the project
           | is discontinuated and has been replaced by something else,
           | it's a waste of time."
           | 
           | So, it might be worth adapting the messaging. For example,
           | there is an awesome-clojure page with a kitchen sink of every
           | possible libs, some of which are dead, and some of which
           | might not be.
           | 
           | Is there a "boring-clojure" page, where, sure, not everything
           | is awesome, but you can be confident that using this lib and
           | that tool and that IDE is going to, basically, "just work"
           | for the foreseenable future ?
        
             | worthless-trash wrote:
             | I can't talk about the life cycle of clojure libraries, but
             | i have seen common lisp libraries that haven't been updated
             | for almost 10 years that work perfectly. There is little
             | the maintainer needed to fix.
        
         | delegate wrote:
         | If you like the language, don't let that stop you. Install
         | leiningen and run: `lein new app my-stuff`. Then type `lein
         | repl` and you should have a repl running.
         | 
         | Alternatively, open the project in IntelliJ with Cursive
         | installed or VSCode with Clava or other supported editors and
         | start evaluating code at the repl.
         | 
         | Go through a few tutorials, then go through one of the free
         | books available online. Don't give up when you're stuck.
         | 
         | The language has a steep learning curve because it requires
         | thinking about the program in a different way than many
         | mainstream languages. But it compensates by giving you many
         | 'aha!' moments which make the day :).
        
           | phtrivier wrote:
           | Well, also, sadly, the first thing I would want to be right
           | now happens to be... a GUI, which seems to be the archnmesis
           | of Java in general, and clojure in particular ;)
        
             | writebetterc wrote:
             | Ain't nothing wrong with Swing or JavaFX :).
        
               | vips7L wrote:
               | Ehhhh they work, but at what cost? If you know them
               | already go ahead, but the other popular desktop ui's are
               | probably easier and more maintainable. I really do wish
               | desktop and mobile in Java was more popular. I'd really
               | like to have one language and ecosystem.
        
             | delegate wrote:
             | If your target is the web browser, then Clojurescript is
             | your friend. There's Clojure Dart for mobile, cljsrn for
             | React Native, Clojure CLR for .Net
        
       | 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
        
         | jwr wrote:
         | Hard disagree: I never used Datomic and likely never will, and
         | I don't feel like I'm "losing some of the language's value".
         | Datomic is a database. You can use any database you like.
        
           | newlisp wrote:
           | Datomic feels like a natural extension of Clojure for storing
           | data--you get no impedance mismatch, you continue working
           | with Clojure's data structures for storing, querying, and
           | writing data instead of dealing with clunky query builders(or
           | SQL strings), and you gain immutability. Sure, you can use
           | any database you like, but then you're playing the same game
           | as every other programming language, ultimately getting less
           | value out of Clojure and making it feel like just another
           | language--at least for applications that require a database.
        
             | jwr wrote:
             | I disagree. I tried to use datalog and it was not a natural
             | extension at all, because of the lack of nil handling. I
             | also found that I do not need (or want) full immutability.
             | 
             | I would not compare it to SQL: I do not use SQL because
             | there is no distinction of in-band and out-of-band data
             | (your data and your commands/queries travel in the same
             | channel, which causes a world of pain). But there are other
             | database approaches that work very well. It's not a problem
             | at all to serialize your data and store native Clojure data
             | structures, even better than datomic does.
             | 
             | In other words, I disagree that Datomic is somehow natural
             | or superior: it is "a" database, excellent for certain
             | applications, not necessarily the best choice for every
             | application.
        
             | huahaiy wrote:
             | Not really. Database is where immutability may not be a
             | good fit, at least not all the time.
             | 
             | In many use cases, database is where application state
             | resides, hence a mutable database is a better fit.
             | 
             | There are Datomic flavored database in the Clojure
             | ecosystem that is specifically design to address this
             | point, e.g. Datalevin.
        
       | 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 - e.g. enterprise cloud
       | information systems and rich interactive web products.
        
         | felideon wrote:
         | As someone who worked with Common Lisp many moons ago, this is
         | the answer I needed to pique my interest in Clojure (again).
        
       | 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...
        
       | jasebell wrote:
       | Done me fine for the last decade. Along with all the other
       | languages that kept me in employment. I still use it daily.
        
       | fernirello wrote:
       | Arne has written, as usual, an excellent piece. Not only it
       | argues its intended points, but it can also be followed by
       | everybody-it brings readers up to speed without assuming any
       | significant background knowledge.
        
       | moomin wrote:
       | Who are these articles for? I feel like Clojure's value
       | proposition is pretty well understood, and every last Clojure
       | pitch can be relied upon to make the same exact points.
        
         | jwr wrote:
         | These articles are necessary to counteract armchair critics who
         | are afraid of unfamiliar things and feel insecure. This crowd
         | is loud: you can hear the choir of "but no one is using it, I
         | tried it once and there were parentheses, I tried it and it was
         | too hard, I hate the JVM" -- there needs to be a voice that
         | says it works (and works well!) for some people.
         | 
         | FWIW, it works for me -- I would not have been able to build
         | and run my business without Clojure. The long-term stability is
         | an especially important trait, under-appreciated by people who
         | do not have a business to run.
        
           | rednafi wrote:
           | It's probably geared toward someone like me. JVM and parens
           | are one angle.
           | 
           | Another is that I get paid to work with distributed systems
           | and databases, and Clojure isn't even part of the discussion
           | in that sphere. Go, Rust, and the usual Python and Node
           | dominate there, so it's hard for me to care.
           | 
           | However, I dislike language monoculture and am curious about
           | why people like the things I might not care about. This blog
           | is for those.
        
             | jwr wrote:
             | > distributed systems and databases, and Clojure isn't even
             | part of the discussion in that sphere
             | 
             | I'm not sure what a programming language has to do with
             | distributed systems and databases, but as another data
             | point, I happily work with distributed systems and
             | databases, using Clojure :-)
             | 
             | (see also https://jepsen.io which I would very much call a
             | "part of the discussion in that sphere", written in
             | Clojure)
        
             | huahaiy wrote:
             | I thought distributed system is exactly one of the things
             | that got Clojure going to begin with. Remember Storm?
             | 
             | As to databases, there are a fountain of databases emerging
             | from the Clojure ecosystem: Datomic, Datascript, Datalevin,
             | XTDB, and friends aside, there is Rama, which is a
             | distributed database (or to replace database?)
        
           | kunley wrote:
           | Where are these mythical armchair critics living normally,
           | what do they do, how much of their time is put into plotting
           | of how to bring a misery for Closure coders?
           | 
           | Point of my sarcasm here is: you guys invoke them by yourself
           | by writing overly defensive or overly religious posts. Then
           | there will be ofc some critics, as with everything: they do
           | not necessarily express a deliberate scheme against Clojure
           | world. They are just some folks with different opinions, and
           | also: very often wrong ones. But, as an advocate, please
           | don't go into an offended teenager mode, when all the world
           | plots against you; because a lot of rhetoric around defending
           | Clojure sounds like that.
        
           | fud101 wrote:
           | The only counter argument that matters to me is there are
           | hardly any jobs.
        
       | kstrauser wrote:
       | I've never used Scala or Clojure, but I heard them discussed a
       | lot in the same circles in the late teens. It seems like Scala
       | kinda vanished from common mention. Whatever happened to it, and
       | what made Clojure take off?
        
         | spoaceman7777 wrote:
         | I think the Java 8+ functional APIs/streaming/etc. kind of
         | stole Scala's thunder. Java has all of the necessary tools to
         | replicate the functional style of Scala now, and it's a lot
         | easier to hire for, so :/
        
           | kstrauser wrote:
           | Ah, got it. So it's not to much that Scala went away, as that
           | Java became Scala?
        
             | valenterry wrote:
             | No, not at all. It's just that Scala was hyped at a time
             | and now it is a mature and stable language and hence
             | "boring".
             | 
             | How often you hear of a language online does not reflect
             | how much it is actually used. Nor does it reflect on how
             | good the language is.
        
             | vips7L wrote:
             | In my opinion, the people who went to use Scala were in two
             | categories: people who wanted functional programming on the
             | JVM and people who just wanted a better Java. As Java
             | progressed and Kotlin launched the people that wanted a
             | better Java either stuck with Java or moved to Kotlin.
             | 
             | Personally, I think Scala is a fantastic language, but it's
             | had breaking changes, a functional only ecosystem, Java ->
             | Scala interoperability is HARD, and the language is
             | complex. Now there is Scala 3 and there are more breaking
             | changes and the tooling landscape hasn't caught up.
        
         | KingMob wrote:
         | I think this is a mistaken assumption. Scala was always more
         | popular than Clojure, and even now, I just checked with Google
         | Trends, and Scala's still searched for 4x more frequently.
        
         | draven wrote:
         | I'd say most of its niches (async with Futures, akka, spark)
         | now have other options. Also, Scala 3 happened.
        
       | jwr wrote:
       | As a data point: I've been running my solo-founder SaaS business
       | for 10 years now using Clojure. It changed my life. It would not
       | have been possible without Clojure and ClojureScript, building
       | and maintaining an app of this complexity would have exceeded my
       | limits.
       | 
       | The article is excellent and I agree with everything in it.
       | 
       | The stability of the language is unbelievably useful. I look
       | around and it seems it isn't valued in many other ecosystems
       | where people have to rewrite their software regularly. I can't
       | afford to rewrite my app.
       | 
       | There will be plenty of armchair critics here, with cliche knee-
       | jerk reactions (parentheses, JVM, startup time, etc). If you
       | intend to form an opinion, I would suggest you read only into the
       | insightful posts, from people who actually used the language, or
       | from critics who present well thought-out criticism, not just a
       | shallow knee-jerk reaction.
        
         | stickfigure wrote:
         | You will find that "whatever language you are most familiar
         | with" is the only one that you will perceive makes it possible
         | for you to build whatever you are working on.
        
       | rednafi wrote:
       | It's great, and I learned a ton from Rich Hickey, despite not
       | fully grokking Clojure or FP in general. I briefly worked at a
       | small Clojure shop with an extremely talented crew. People were
       | excited about FP and writing real business logic with it. My
       | stack was different there.
       | 
       | The problem started when the honeymoon phase ended, and the
       | codebase grew as the business gained traction. Dynamic typing
       | became a burden, and once the key people moved on, they struggled
       | to hire developers who wanted to write Clojure.
       | 
       | Also, JVM juju shooed many away. After I left, a coworker told me
       | they had started rewriting part of it in Go, and that was going
       | alright. Now, their stack mostly consists of Python for LLM stuff
       | and Go for the main backend. There's still some Clojure running
       | legacy systems that haven't yet been migrated over.
        
         | chamomeal wrote:
         | I've been having a lot of fun messing with clojure, but the
         | dynamic typing really grates on me.
         | 
         | At your clojure job, we're y'all using spec? I haven't looked
         | into it yet, and I'm wondering how much it mitigates the
         | annoyances of dynamic types
        
           | rednafi wrote:
           | It was in alpha stage and changing rapidly when they were
           | considering it. But it's similar to Python's type hints and
           | isn't enforced by the compiler. However, that's better than
           | nothing.
        
             | noodletheworld wrote:
             | In what way is clojure.spec similar to python's type hints?
             | O_o
        
           | noodletheworld wrote:
           | I don't think spec with solve issues you are having about
           | dynamic types.
           | 
           | Spec is about asserting structure at domain boundaries; once
           | you're inside a context, it will not do anything.
           | 
           | i.e. If you're connecting stuff together and you want to make
           | sure the state is correct as you pass between contexts ->
           | great!
           | 
           | If you're writing stuff and _internally_ you miss having a
           | strong type system... uh... I don 't think it's really going
           | to help you.
        
             | geokon wrote:
             | why not just program to protocols?
             | 
             | For complex data structures I typically just hide details
             | behind a protocol and deal with the set of interface
             | functions.
             | 
             | You can then freely mess with the internals and not worry
             | about details
        
               | mrkeen wrote:
               | I don't know enough about protocols. Will the compiler
               | stop you if you misuse them?
        
               | serpix wrote:
               | The compiler will not know if a protocol is not passed to
               | a function expecting a protocol. Whereas a static typing
               | language will not compile.
               | 
               | Similarly nothing prevents invoking missing functions of
               | a protocol, you will only know during runtime.
        
               | geokon wrote:
               | Well you're typically not thinking of a compilation step
               | with Clojure.. so I found the original question a bit
               | not-applicable
               | 
               | The goal isn't to introduce .. a compilation step? but to
               | have the program blow up in the spot where there is an
               | type mismatch. If you don't use a protocol you may not
               | blow up, you may generate a nil, and you may blow up much
               | further down the line (or not at all)
               | 
               | In the rare instances where dynamic types cause problems,
               | they're virtually always something convoluted like that.
               | The protocol design pattern describes the interface and
               | protects you from hard to debug situations
        
               | harperlee wrote:
               | In my experience (mainly when trying to understand the
               | implementation of core.logic), the problem with protocols
               | is that the code inspection tools choke on them.
        
           | MarkMarine wrote:
           | Coming from a love of strong typing (scala) clojure dynamic
           | typing was a real adjustment.
           | 
           | One thing I grew to really love is how small my changes were
           | when I'm just adjusting a decidedly brownfield chain of
           | functions that operate on data. With go in place at work, I
           | added a couple fields to a core data type in my business and
           | I ended up with thousands of lines of changes to pipe them
           | everywhere. Doing the corresponding change in clojure would
           | be <100 lines. I do miss the feeling I get with Haskell that
           | if it type checks, I'm (maybe) good, but like Rich says
           | "List[A] -> List[A] tells me almost nothing about the reverse
           | function."
        
             | dwohnitmok wrote:
             | The Haskell type `[x] -> [x]` (the equivalent of `List[A]
             | -> List[A]`) tells you an incredible amount about the
             | function. It tells you that the function must calculate a
             | subset of a permutation of the input list. The function
             | cannot be anything else (or else it will crash or hang). In
             | a language with stricter requirements you can omit even the
             | crash/hang caveat.
             | 
             | Don't underestimate the amount of information even simple
             | type signatures contain!
        
               | tromp wrote:
               | Not necessarily a permutation; e.g.                   f
               | :: [a] -> [a]         f [] = []         f (x:xs) = x: x:
               | f xs
        
               | tome wrote:
               | Yeah, Hickey was just wrong about this. For me, watching
               | his talks goes like this:
               | 
               | Hickey: I value X, Y, Z
               | 
               | Me: Yeah man!
               | 
               | Hickey: We get great consequences A, B, C
               | 
               | Me: Ah yeah, I love programming like that. That's why I
               | love Haskell!
               | 
               | Hickey: That's why Haskell is bad.
               | 
               | Me: err, what!?
               | 
               | > It tells you that the function must calculate a subset
               | of a permutation of the input list
               | 
               | As tromp pointed out, "permutation" is technically
               | incorrect. You mean something like "a list formed only
               | from elements of the elements of the input list, and the
               | particular arrangement is independent of the values of
               | the input list"!
               | 
               | Not sure why you were downvoted though.
        
           | jimberlage wrote:
           | The tooling around static types is worlds better than any
           | tooling around spec - it's not like working with a static
           | typing system, unfortunately.
        
         | kamaal wrote:
         | >>Also, JVM juju shooed many away. After I left, a coworker
         | told me they had started rewriting part of it in Go, and that
         | was going alright.
         | 
         | Golang can make even Python look terse.
         | 
         | There's practically 0 abstractions to meaningfully tame large
         | code bases. You just end up writing same/similar code patterns
         | over and over again.
         | 
         | If you are willing to go down that path I'd recommend using
         | Java entirely. You get the full enterprise thing.
        
       | iLemming wrote:
       | I love writing Clojure. Whenever I say that publicly, there are
       | inevitably some voices challenging my stance with skepticism,
       | criticism, and attempts to discredit whatever I say provides
       | practical value for me. Then I have to explain to them, "no, it's
       | not the only language I know," "yes, I've used dozens of other
       | languages before," "yes, including languages with robust static
       | type systems as well."
       | 
       | And you know what? Finally, I realized - I don't have to explain
       | to anyone in exact detail why I have not found the same deep love
       | in C, C#, Python, Javascript, Typescript, Ruby, Go, Java, Kotlin,
       | Swift, Lua, Haskell, and many others. Why do I need anyone's
       | permission to love a tool? I love it, and I love it for many
       | reasons - theoretical, practical, emotional, fiscal.
       | 
       | Sure, I can get behind your excitement for Rust, Kotlin, OCaml,
       | Elixir, Julia - you name it, but please, please do not try to
       | "educate" me about my choices. I don't care about YOUR personal
       | predicaments with Clojure/Clojurescript/Babashka/nbb, even
       | Fennel. You find Clojure not to be worthy of your time - it's
       | YOUR loss. My love for Clojure is not due to MY skill issues, not
       | the result of MY inexperience, not because "I'm in a bubble," or
       | "I don't know any better," or have zero knowledge of type
       | systems, category theory, OOP or design patterns.
       | 
       | Sure, Clojure is not without deficiencies - no tool is ever
       | perfect. Yet pragmatically, no other programming language in the
       | category of general-use PLs today satisfies me more than Clojure,
       | no other language is nearly as joyful to use. I'm sure at some
       | point my stance will change, I will find some other "perfect"
       | language for me, and 100% guaranteed - it will too have some
       | deficiencies and people will be arguing for the merits of
       | choosing it for the job. Until that day, let me just say it again
       | - "I fucking love Clojure!"
        
         | j45 wrote:
         | The use of prejudice type behaviour towards others using a
         | particular programming language based on hearsay or unknown is
         | not ok, but also not something new.
         | 
         | The few folks I know using it are very happy with it, and are
         | very experienced, and talented talented polyglots themselves.
         | 
         | For that reason I'd not rule it out, even if I'm not looking to
         | make a jump or change, but I might try it out.
        
         | golly_ned wrote:
         | I've never seen anything but praise for clojure.
        
           | iLemming wrote:
           | > I've never seen anything but praise for clojure.
           | 
           | I've seen plenty of tomatoes here on the orange site, thrown
           | at Clojure.
           | 
           | Interestingly, years ago, when I was deciding if I should
           | learn Clojure, I have typed into Google "why Clojure sucks".
           | That's actually my usual "research technique" for any new
           | tool - after the initial intro and the wikipedia pages, I
           | typically do that and try to find some criticism, in order to
           | remain level-headed. And guess what? To my surprise, instead,
           | I found a plenty of compelling reasons to learn the damn
           | thing, which I did. That has changed my life, not
           | exaggeratingly, quite for real.
           | 
           | So my conclusion and advice to young programmers? Use
           | whatever tools make you happy. Don't worry about their
           | popularity, don't listen to couch-surfing "experts", try them
           | for yourself. Be skeptical, first and foremost about your own
           | reservations, thoughts, and feelings - something you dislike
           | initially may change your perspective later. Conversely, be
           | looking out for even better ways - remember, it's always
           | possible to find renewed joy for the craft, even after
           | decades of trying different things. There's always something
           | out there that would feel like it was made for you to enjoy
           | it.
        
           | roenxi wrote:
           | You've never seen someone encounter Clojure stacktrace-barf
           | when something breaks before. The language isn't perfect.
           | Although it is one of the few I've encountered that does
           | immutability properly and that is great.
           | 
           | The stacktrace-barf has improved a bit in recent versions as
           | I recall, although I've lost the ability to see them by now.
        
           | sundarurfriend wrote:
           | I was gonna reply something similar too. The only "counters"
           | people have when talking about Clojure (that I see, as a non-
           | Clojurian) are pretty weak, and are usually: "it uses JVM,
           | and JVM bad mmmkay" and the typical lazy dismissal of Lisps
           | as "omg it's parantheses everywhere".
        
             | worthless-trash wrote:
             | My new favourite is am seeing is clojure doesnt have enough
             | syntactic sugar.
             | 
             | SMH.
        
             | maleldil wrote:
             | Add "dynamic language" in this day and age where everyone
             | thinks static languages are cool again.
        
           | ldite wrote:
           | The dynamic typing and "everything is a map" can be a PITA.
           | At the moment I'm working on a codebase that has I/O to JSON
           | APIs, Avro schemas and postgres databases. That means that a
           | field called "date" can be either a string, integer days
           | since the epoch or a Java Date, and (because this codebase
           | isn't great) there's _no way of knowing_ without tracing the
           | call stack.
           | 
           | With the right discipline (specs, obsessively normalising all
           | data at the boundaries, good naming conventions) this
           | wouldn't have been a problem, but that discipline is
           | optional, and headbanging aggravation results.
           | 
           | (This is, of course, a generic "dynamic typing" problem, but
           | that's a key feature of Clojure)
        
             | mkreis wrote:
             | I'd emphasize that it's a problem with your particular code
             | base. If you set it up correctly, all dates are properly
             | parsed at the boundaries and you would only deal with one
             | type of date inside your app. I'm working on a large
             | Clojure app with a lot of date handling and never had any
             | issues. For me, a date is always juxt/tick date.
        
               | ivanb wrote:
               | The parent comment illustrates the problem with one clear
               | example. In real-world code functions pass around
               | amorphous maps, they add, subtract and transform fields.
               | There is no way to know what's being passed around
               | without reading the source of the whole chain.
               | 
               | Statically typed languages reduce the need to know how
               | the data is structured or manipulated. The market has
               | clearly chosen this benefit over what Clojure can
               | provide.
        
               | erichocean wrote:
               | > _There is no way to know what 's being passed around
               | without reading the source of the whole chain._
               | 
               | But that's not what a Clojure dev would do.
               | 
               | 1) We use Malli [0] (or similar) to check specs and
               | coerce types if needed at every point. Checks can be left
               | on in production (I do), or disable-up to you.
               | 
               | 2) If the coercion is difficult, use something like
               | Meander. [1]
               | 
               | 3) If even that isn't straightforward and you need actual
               | logic in the loop, use Specter. [2]
               | 
               | 4) If you're not sure what going on at intermediate
               | steps, use FlowStorm [3].
               | 
               | 5) But you're going to be processing a lot of data you
               | haven't seen before! Use, Malli with test.check [4] and
               | make use of property-based testing with generators.
               | 
               | None of this is "advanced" Clojure, this is bread-and-
               | butter stuff I use every day.
               | 
               | 6) Need a Notebook-like experience to get better
               | visualization of intermediate data? Use Clerk [5].
               | 
               | 7) Need special checks on API usage within your codebase?
               | Use clj-kondo [6] with custom linters. They're less than
               | 10 lines each.
               | 
               | Unlike default-mutable languages, or typed, it's safe and
               | easy to use libraries with Clojure and they tend to have
               | very little churn. Total opposite from Python or
               | JavaScript (if you're used to that).
               | 
               | It's almost impossible to give the impression of what it
               | is like to develop with Clojure if you've only ever used
               | languages with static typing, or languages from the Algol
               | family.
               | 
               | Honestly, I hated Clojure's syntax at first BECAUSE I
               | COULDN'T READ IT, and I loathed "structural editing."
               | After 2-3 weeks, I read it just fine and it's hard to
               | remember I ever couldn't do so. Now I like it, and
               | structural editing makes it so easy to change your code,
               | I couldn't live without it at this point.
               | 
               | Basically, all my "fears"/dislikes were unfounded--it was
               | a skill issue on my part, not a problem with Clojure.
               | 
               | [0] https://github.com/metosin/malli
               | 
               | [1] https://github.com/noprompt/meander
               | 
               | [2] https://github.com/redplanetlabs/specter
               | 
               | [3] https://www.flow-storm.org/
               | 
               | [4] https://github.com/clojure/test.check
               | 
               | [5] https://clerk.vision/
               | 
               | [6] https://github.com/clj-kondo/clj-kondo
        
               | maleldil wrote:
               | That's a lot of different tools for something that could
               | simply be a statically defined type with compile-time
               | checking.
        
               | erichocean wrote:
               | No it can't, but hey, there's a talk about that!
               | 
               | The Value of Values:
               | https://www.youtube.com/watch?v=-I-VpPMzG7c
               | 
               | Using types to model data is a terrible idea.
        
               | hombre_fatal wrote:
               | Most people don't use those libraries, nor do most
               | libraries use those libraries. They don't help me
               | understand most code out there beyond my carefully
               | orchestrated app code. I'm back to reading the source.
               | 
               | But this long list of runtime libraries is definitely a
               | downside of Clojure. It's people trying to grapple with
               | things mostly solved with static typing where you can
               | just write a(b(c())) and it fails before it hits your
               | fancy yet-another-thing-to-learn Malli library in
               | runtime.
               | 
               | They might be great libraries, but you're only seeing one
               | side of the trade-off.
               | 
               | I learned Emacs with evil-mode, paredit, nrepl/cider, and
               | Clojure in my early 20s and used them for six years, and
               | I was pretty gung-ho about it like you. But eventually I
               | started using static typed languages for work and decided
               | that I couldn't go back. It's like trying to read
               | Javascript after you've spent five years with Typescript.
               | You just think "wow, I can't believe I did that for so
               | long."
               | 
               | And I'm remembering times I've used paper and pencil to
               | figure out how map is being transformed as it's passed
               | through library code. I don't miss that.
        
             | flavio81 wrote:
             | >That means that a field called "date" can be either a
             | string, integer days since the epoch or a Java Date, and
             | (because this codebase isn't great) there's no way of
             | knowing without tracing the call stack.
             | 
             | But this is because JSON is an untyped data structure. (And
             | btw, a flawed one...)
             | 
             | You would have this problem in any programming language.
        
           | ddellacosta wrote:
           | After writing Clojure/CLJS for a decade professionally I
           | think it's a toy language that is completely inappropriate
           | for industrial use. But, at this point it's not worth my time
           | to talk about it past that
        
         | gloomyday wrote:
         | Through the last decade, I have found that programmers'
         | judgment of technologies, tools, and languages are incredibly
         | noisy. It is hard to make correct decisions based on opinions
         | alone, and design by committee is a real thing.
         | 
         | Common Lisp was the most mind-blowing language I ever touched,
         | and it seems the creator of Clojure really filled the gap
         | between the brilliant simplicity of Lisp as a language and the
         | access to a mature ecosystem. Maybe I should try Clojure as my
         | next language (I am enjoying Rust for now; Rust macros are also
         | cool, but way more complicated)...
        
           | erichocean wrote:
           | If you already like Common Lisp, what Clojure brings are:
           | 
           | 1) runs on the JVM, access to any Java or Python library
           | within Clojure without wrappers
           | 
           | 2) an immutable-by-default language with a standard library
           | that takes advantage of it
           | 
           | 3) the best out-of-the-box concurrency story of any language
           | I know of
           | 
           | 4) a very well-developed ecosystem for developer tooling and
           | general project stuff
           | 
           | Common Lisp is very fun, but the stress level is definitely
           | higher with it due to the mutability and the generally less
           | well-designed APIs. Only lists are actually functional,
           | concurrency is YOLO-tier, etc.
        
             | flavio81 wrote:
             | > runs on the JVM, access to any Java or Python library
             | within Clojure without wrappers
             | 
             | If you already like Common Lisp, ABCL (Armed Bear Common
             | Lisp) is a mature fully ANSI Common Lisp-compliant
             | implementation, that runs on the JVM and can instance or
             | load Java classes or call Java methods without wrappers and
             | in only one line of code.
             | 
             | > the best out-of-the-box concurrency story of any language
             | I know of
             | 
             | Lots of concurrency models also available on Common Lisp,
             | including async, channel-based, etc.
             | 
             | > Only lists are actually functional, concurrency is YOLO-
             | tier, etc.
             | 
             | I'm sad you had that experience, but there is tons of solid
             | concurrency support in Lisp, for example lparallel is
             | awesome.
             | 
             | Clojure is nice as a JVM language alternative, that is,
             | better than Kotlin, Groovy, etc.
             | 
             | However the loss of the great interactive development
             | facilities that Common Lisp has is a major, major downside.
             | Interactive development is what makes CL (and also
             | Smalltalk/Pharo) great.
        
         | regularmother wrote:
         | Did you or any of your fellow devs have ADD or ADHD? How did
         | they adapt to dynamic types?
         | 
         | I have ADD and I once heard that devs with ADD/ADHD have an
         | incredibly small heap size for context but compensate for their
         | weakness by being great at solving logical problems in that
         | small heap. Types have been essential for me when functioning
         | in code bases. I really struggle with pure JS and untyped
         | Python.
         | 
         | Clojure was similarly hard for me. What tools and/or techniques
         | do such folks use for comprehending already written Clojure
         | code?
        
           | itsfine2 wrote:
           | Types and other techniques as an accessibility tool for the
           | ADHD brain - Michael Newton talk
           | https://www.youtube.com/watch?v=vd1-rAIYV6I
        
           | cardanome wrote:
           | Not everyone with ADHD struggles with small heap size.
           | 
           | Even if I have a smaller total heap size (maybe), personally
           | my hyper focus allows me to nearly dedicate all the heap
           | space to the specific task at hand. I probably outperform
           | neurotypical people here. I just can't have anything else in
           | my head. Task switching kills me.
           | 
           | So it is hard to say cause everyone is a bit different.
           | 
           | For me the interactive, REPL-based workflow makes my ADHD
           | brain very happy. Always having a program running is really
           | nice.
           | 
           | Plus immutability makes it much easier to reason about
           | things.
           | 
           | I do like static typing as well and I could see how it might
           | help. I strongly believe that gradual typing allows for the
           | best of two worlds, so that you can do both exploratory,
           | interactive programming and type driven programming,
           | depending on your needs.
           | 
           | Not sure how well the solutions for gradual typing in Clojure
           | work though. I have only experience with Common Lisp. Coalton
           | might the exactly what you need: https://github.com/coalton-
           | lang/coalton
        
           | doall wrote:
           | Reducing cognitive load is the key. Several approaches I
           | usually take are: 1. Make strict rules for code convention,
           | especially naming things, and stick to that. 2. Use
           | intermediate variables (let binding) often 3. Turn meaningful
           | code block to a function often 4. Write Clojure specs and
           | turn them to docstrings
           | 
           | In addition to that, a real REPL programming really helps to
           | do small tests and understand the code quickly, immutable
           | data structures with data-oriented approach and locally
           | scoped code blocks combined with structural editor are
           | godsend as well.
        
             | owkman wrote:
             | Do you have any resources showing what this type of coding
             | works in the real world? I keep running into this same
             | types issue when I use languages without types specified
             | everywhere, where the cognitive load gets too much for non-
             | trivial projects. I would be pretty unhappy writing python
             | without type hints and tools that check these for
             | correctness built into my workflow for example.
        
               | doall wrote:
               | This was from my experience that I thought may work for
               | others too. Types may help in some sense, but is not
               | enough and sometimes even add extra load especially on
               | heterogenous data structures. Before using any tools
               | beside basic IDE features, I think there are fundamental
               | things you can do to reduce cognitive load, such as
               | focusing more on code design, convention, structures,
               | naming, testing, documentation, which can be applied
               | whatever language you use.
        
           | flavio81 wrote:
           | >How did they adapt to dynamic types?
           | 
           | You mean dynamic typing, I understand.
           | 
           | Clojure (and Common Lisp) is strongly typed, so if you expect
           | type A and you give a value of type B, an error will be
           | raised.
           | 
           | On Common Lisp, which is an interactive development language,
           | you just inspect the stack frame where the error was raised,
           | find the problem, correct the code, recompile your function
           | (while the code is running), and "restart" the stack frame,
           | so the execution continues (without having to restart or
           | redeploy everything and try to replicate the bug). Thus, it
           | is no big deal at all.
           | 
           | On Clojure i'm not so sure how extensive is the interactive
           | support. But there is "spec", which can help.
        
         | rendaw wrote:
         | So I think people probably hear "I love clojure" and take it as
         | advocacy. I mean, maybe it isn't supposed to be advocacy, but
         | "I keep hearing people say they love X" is a decent reason to
         | start using something, and I think people are influenced that
         | way.
         | 
         | When you're writing software you benefit from libraries the
         | community made, and lots of people end up writing libraries and
         | contributing back. It's possible Zig is much better for C, but
         | they're failing to gain users due to lots of C developers
         | continuing to use C for new projects, whereas if there were
         | more users maybe the Zig ecosystem would be larger, making it
         | easier to write larger pieces of software.
         | 
         | And I think basically all software is a collaborative effort.
         | Users have investment in tools they think are useful, and
         | frequently contribute or even take over maintenance on critical
         | software. In that case they need to deal with whatever
         | technical decisions that project made. Even commercial software
         | can be abandoned as a buggy mess due to technical choices
         | forcing users to migrate, or eventually open sourced (blender,
         | doom, etc) in which case private technical choices become
         | public. Also I think a lot of people have been forced to
         | contribute (i.e. professionally) to projects that initially
         | made very poor technical decisions and have been scarred by it.
         | 
         | No tool is perfect, and abstract technical debate is awful, but
         | I think it's hard to say there isn't worse and better software,
         | and I think it's worth the effort to put in effort to debate to
         | try to discern and move from worse to better tools since the
         | whole community benefits that way.
         | 
         | Edit: re-essayed
        
       | patcon wrote:
       | I've worked around an open source Clojure codebase for a few
       | years. I've grown to dislike Clojure by virtue of the culture it
       | apparently fosters. As a community organizer in some vibrant
       | decentralized spaces, reading articles from inside the community
       | gives me ick feelings. There's a strange phenonemon involved when
       | you have a diehard community that continually extols the virtues
       | of the language, while the popularity of the language itself
       | halves its open source marketshare every few years.
       | 
       | I mean, you have to try really hard to cultivate a community of
       | people who have a deep love for something, but for some reason
       | can't see what is actually wrong with it that drives ppl away.
       | Passionate users are usually a boon, but apparently not for
       | Clojure. But people somehow seem to build great companies with
       | it. It's strange, and very specific to Clojure culture. I can't
       | help but assume its failure to capture market is tightly tied to
       | its leadership style and/or leader worship.
       | 
       | Anyhow, these are just hot-takes from the margins. I'm sure that
       | passionate users will have something to say, or maybe downvote
       | me.
        
         | j45 wrote:
         | How to support the creation of beginners might be a different
         | topic (and not a new one to technologies) to the offer of the
         | technology itself.
         | 
         | How was your experience in working with the existing Clojure
         | codebase?
        
           | patcon wrote:
           | Very true. Thanks for noting that.
           | 
           | The codebase was democracy-related civic tech software. I was
           | a bit biased against Clojure because I wished for the world
           | to show up in the codebase, but it was written in an uncommon
           | language that scared away most every coder who showed up with
           | curiosity.
           | 
           | Probably just the wrong language for the culture I wished to
           | exist around the software. Plus the maintainers used Rich's
           | essays to emphasize their desired ethos of "singular vision"
           | development, which I admittedly became resentful of.
        
             | patcon wrote:
             | I thought of an analogy later, which perhaps colors my
             | experience -- writing democracy software in Clojure felt
             | disappointing, loaded with a power dynamic kinda like the
             | Catholic bible and service being conducted in Latin before
             | the 1960s.
             | 
             | It was not a language "of the people". And not just in how
             | uncommonly known it was, but even the philosophy in how the
             | language governed itself. It felt harmful to me: the cross-
             | pollination between the ethos of the Clojure project (via
             | the well-intentioned developer who brought pieces of
             | Clojure culture into conversations and discussions) and the
             | democracy project.
        
         | lukev wrote:
         | I think there's something here. I'm not sure it's a bad thing.
         | A negative framing might be that there's a sort of elitism. A
         | more positive framing might be that it simply reflects a
         | tension between different, valid views of how to build software
         | which are sometimes (but not always) in tension.
         | 
         | After all, an elitist can also sometimes be right.
         | 
         | Disclosure: I say this as someone who has been about as deep as
         | you can go in the Clojure community.
        
           | KingMob wrote:
           | As someone who was equally deep (I worked with you and the
           | Danes), I think a lot of that elitism isn't just about
           | building software.
           | 
           | It's a large part of why I've stepped back from clj these
           | days.
        
           | patcon wrote:
           | > A negative framing might be that there's a sort of elitism.
           | A more positive framing might be that it simply reflects a
           | tension between different, valid views of how to build
           | software which are sometimes (but not always) in tension.
           | 
           | I really like this framing of "in tension". Multiple things
           | can be true. I think it represents a healthy tension that I'm
           | grateful exists, even if I'd not personally wish to be
           | operating in that specific tension. But I'm sure the people
           | living in are different than me, and can do things in this
           | world that I could not :)
        
         | eduction wrote:
         | I started four years ago and in some ways still feel like a
         | beginner. I have found the community super welcoming and
         | positive - I've asked questions on r/Clojure, clojureverse, Ask
         | Clojure and the Slack. A couple of my Slack and Ask Clojure
         | questions were in retrospect poorly researched and I still got
         | super helpful replies.
         | 
         | Did you encounter some hostility?
        
         | neillyons wrote:
         | > really hard to cultivate a community of people who have a
         | deep love for something, but for some reason can't see what is
         | actually wrong with it that drives ppl away
         | 
         | Elm is another example
        
       | hlship wrote:
       | I've been working in Clojure now for about 12 years. Maybe 12+
       | years of Java prior to that.
       | 
       | I've created some great apps, and great libraries (in both
       | Clojure and Java).
       | 
       | I often describe Clojure as "the least worst programming
       | language", which is an off-handed complement, but I think
       | accurate. Things you don't like can generally be fixed (at least
       | locally) using macros and libraries. The core is strong, a good
       | basis for building things ... and as described all over this
       | thread, stable.
       | 
       | As you master your tools, you gain a level of speed and precision
       | in your work that I have not found elsewhere. The REPL-oriented
       | workflow is a central value proposition in Clojure, and many
       | features (and a few limitations) of the language exist to
       | properly support it.
       | 
       | Working in Clojure feels like I'm working "with" my code, molding
       | it like clay. My prior experiences in Java and Objective-C were
       | so much slower, with long code-compile-test-debug cycles that are
       | compressed down to instantaneous responses in the running REPL.
        
         | rootnod3 wrote:
         | Haven't worked much in Clojure, but I have the same experience
         | with Common Lisp. The malleability and live image workflow is
         | just very pleasant to work with.
        
           | erichocean wrote:
           | Clojure is like that, but because data structures are default
           | immutable, and all of the standard library (and the vast
           | majority of 3rd party libraries) are also default immutable,
           | the stress level is much lower.
           | 
           | You can still get mutability and I do this on every project.
           | But it's a very small percentage of the code, less that 1%,
           | and also well-defined.
           | 
           | Something like FlowStorm [0] isn't really practical in
           | anything but Clojure, and things like Clerk [1] are easy and
           | very natural.
           | 
           | [0] https://www.flow-storm.org/ [1] https://clerk.vision/
        
             | rootnod3 wrote:
             | I know. What I just miss in other implementations is the
             | live reflection in the SBCL REPL via Sly/Slime for example.
             | And conditions.
             | 
             | When I do CL, I try to code it in a more immutable style
             | and avoid things like self until I get my own version
             | bootstrapped.
        
         | eddd-ddde wrote:
         | How does the REPL approach scale in very large codebases? I.e.
         | code that talks to multiple services, complex configurations,
         | etc..
        
           | huahaiy wrote:
           | Scales very well.
           | 
           | Immutable data pairs great with REPL.
           | 
           | Because data are immutable, you don't need to care about
           | where that data come from and where it will go. Just focus on
           | what you need to do with that data at the point you work.
           | 
           | Everything is localized due to immutability.
        
           | m1n1 wrote:
           | I worked with a 60K LOC thing* that talked to multiple
           | services and had complex configuration. Ran fine on my laptop
           | pointed at the company's dev env.
           | 
           | The REPL let me test my changes while inside the thing as it
           | ran. No problems. Someone wrote a nice *recording* debugger
           | too which helped immensely -- no more "oops, I'm past the
           | interesting part and have to start over"
           | 
           | * in prod we usually give it a small number of large
           | instances
        
           | ludston wrote:
           | Even better than in small ones, because you don't need to
           | spend 60 seconds building and restarting the application
           | after changing one line: You simply redefine a single
           | function at runtime and them can test the effect immediately.
        
           | thom wrote:
           | I use Integrant to make systems out of components that are
           | tied together at runtime. I have the option of running real
           | versions or mock versions in tests or the REPL, with config
           | drawn from the environment or config files or parameters. I
           | can boot or reboot any combination of components at will.
           | It's fairly easy to divide and conquer this way.
        
             | wry_discontent wrote:
             | I like integrant, but I feel like a lot of the examples I
             | see use it for each web endpoint, which seems like a
             | massive amount of overkill to me. I tend to use it just for
             | the router, but it sometimes feels like I'm not using the
             | library to its full potential with that.
        
               | thom wrote:
               | Do you have an example? On the face of it I agree that
               | seems like a baffling thing to do.
        
           | iLemming wrote:
           | https://polylith.gitbook.io/polylith
        
         | gavmor wrote:
         | I played with Clojure just a bit in 2014 because I wanted to
         | write GUIs in Om, and this gave me a seriously warped habit of
         | calling React.el('div',...) for a while. Sorry not sorry.
         | 
         | I'm used to using TDD for fast feedback as I'm molding my code.
         | Do you miss unit testing? Or, do you find that the REPL in no
         | way obviates unit testing?
         | 
         | And, do you miss static typing?
        
           | huahaiy wrote:
           | REPL code is copy/pasted straight into tests. So really, REPL
           | is for helping write tests.
           | 
           | BTW, when Clojurians talk about REPL, it's not about that
           | separate window where you type and run the code as in other
           | language such as python. They are talking about an invisible
           | REPL running behind the scene, to which they send code within
           | their editors, and the results show up in the editors too.
           | 
           | There's no need to "miss static typing" in Clojure. If I need
           | static typing, I just write deprotocol and deftype in
           | Clojure, as many Clojure libraries do.
        
             | ndr wrote:
             | Thank you, this is the most concise description I've seen
             | for the REPL. That gets often lost due to the curse of
             | knowledge.
             | 
             | It's a completely different thing to be coding "from within
             | your running program" and it's hard to signal that to who
             | has never tried.
        
             | lkitching wrote:
             | Neither defprotocol nor deftype introduce static typing
             | into Clojure. Errors in their usage are not checked
             | statically and are only discovered at runtime.
        
               | rrgok wrote:
               | So what happens at runtime if errors are found?
        
               | synthc wrote:
               | you get runtime errors with a long JVM stacktrace
        
               | erichocean wrote:
               | If you paste into Claude, it will instantly tell you
               | what's going on.
        
               | huahaiy wrote:
               | No, defprotocol and deftype have the same properties as
               | Java interface and Java classes, and the types are
               | checked at compile time. This is static typing. Period.
               | Clojure is a compiled language, it does check typing
               | during compilation.
        
               | lkitching wrote:
               | Protocols do not work like Java interfaces or classes.
               | Their methods are compiled into regular functions which
               | lookup the implementation to use at runtime based on the
               | runtime type of the receiver. Compilation will check for
               | the named function but doesn't do any further checking.
               | Given the following protocol and implementation:
               | (defprotocol P         (method [this ^Integer i]))
               | (extend-protocol P         String         (method [s i]
               | (.substring s i)))
               | 
               | both (method "test" "call") and (method 1 2) will be
               | accepted by the compilation phase but will fail at
               | runtime.
               | 
               | Of course there's no requirement for Clojure code to be
               | AOT compiled anyway so in that case any name errors will
               | still only be caught at runtime when the compilation
               | happens.
               | 
               | Type hinted bindings are only converted into a cast and
               | are not checked at compilation time either e.g.
               | (defn hinted [^String s] (.length s))       (hinted 3)
               | 
               | will be accepted but fail at runtime.
               | 
               | deftype is only used for Java interop an is also not a
               | form of type checking. The methods will be compiled into
               | Java classes and interfaces, but the implementations
               | defer to regular Clojure functions which are not type
               | checked. You can only make use of the type information by
               | referencing the compiled class files in Java or another
               | statically typed language, using them from Clojure will
               | not perform type checking.
        
               | huahaiy wrote:
               | deftype IS a Java class, it's not compiled into something
               | else. What is a Clojure function? A Clojure function is a
               | Java class. Clojure is a compiled language, so it does
               | check types, just like Java check types.
               | 
               | So if you use defprotocol and deftype for every domain
               | objects in your code, your code won't compile if there's
               | a type error. Try it.
               | 
               | BTW, that's the way many Clojure libraries are
               | implemented. These libraries rely on dispatch on type to
               | work, so they are taking advantage of the type checking.
               | 
               | Of course, you will say, "oh, clojure is not normally
               | AOT, so it's not dong the checks.", but that's another
               | issue. The issue at hand is this: can you write Clojure
               | such that types are checked at compile time. The answer
               | is YES.
               | 
               | The compiler may run only when you run the program,
               | that's a different issue. You are confusing these two
               | issues.
               | 
               | If you want a separate compile stage, then basically you
               | are already excluding runtime compilation, i.e. you are
               | arguing against runtime compilation. So it's not really
               | about typing, but about how you want to run the program.
               | Isn't it? You want AOT for everything, you don't want
               | runtime compilation. That's it. It has nothing to do with
               | types.
        
           | eigenhombre wrote:
           | Not the OP but:
           | 
           | One can develop with TDD in Clojure quite smoothly depending
           | on choice of tooling; with CIDER in Emacs there are keyboard
           | shortcuts to run tests for the current namespace or the
           | entire project, so feedback can be very fast (if your tests
           | are fast). I've also used (some time ago) test runners that
           | stay running and re-test when a file is saved.
           | 
           | In fact, it can be nice to do one's explorations in the REPL
           | and then reify one's discoveries as tests.
           | 
           | Regarding types: I will say that working on larger Clojure
           | (and Python) projects with somewhat junior teams made me more
           | curious about type systems. Clojure's immutable collections
           | and the core abstractions they are built around are great,
           | but it can take some skill and discipline to keep track of
           | exactly what kind of data is flowing through any particular
           | part of your program. But, there is some support for a la
           | carte strictness in the language via Spec, Malli, structured
           | types, etc.
        
             | hhhAndrew wrote:
             | > In fact, it can be nice to do one's explorations in the
             | REPL and then reify one's discoveries as tests.
             | 
             | This is how I wrote unit tests when I worked on
             | Mathematica: try out every edge cases of the function in a
             | notebook, and then use a tool to extract all the
             | input/output cells and convert them to tests. I didn't know
             | the term reify for this practice, I like it!
        
               | erichocean wrote:
               | Reify is a general term, it means to "make concrete" (or
               | to "make real" depending on the usage) something that is
               | previously fuzzy or abstract.
               | 
               | When you make a concrete subclass of an abstract class,
               | you are "reifying" that class. When you made the abstract
               | class from the concept of something, you are "reifying"
               | that concept.
               | 
               | It's a fun word.
        
         | pjmlp wrote:
         | Not the same thing, but having something like JRebel can get
         | quite close, and even if jshell isn't the best example of REPL,
         | it isn't that bad either.
        
         | Byamarro wrote:
         | Maybe I miss what REPL really is, but...
         | 
         | If REPL is the main value proposition, how is it better from
         | average JavaScript development? Dev tools allow you to
         | basically interactively work with your code.
        
           | cess11 wrote:
           | You can keep a JVM running in the background with your
           | project loaded and send stuff there from your IDE/editor.
           | 
           | I don't think this is possible with JavaScript.
        
             | dmos62 wrote:
             | You can eval strings in Javascript, so pretty sure that's
             | possible.
        
               | cess11 wrote:
               | Looking around I don't find any maintained projects for
               | this purpose.
        
               | stronglikedan wrote:
               | It's just a native function named eval(), so I wouldn't
               | expect to find projects built up around it.
        
               | cess11 wrote:
               | That's not enough, there ought to be IDE/editor
               | integration and so on.
               | 
               | Here's one such project: https://github.com/swank-
               | js/swank-js
        
               | throwup238 wrote:
               | Quokka.js would probably be the nearest JS equivalent.
        
             | snarkyturtle wrote:
             | So they try to make the least-worst JVM environment which
             | is great if you're dead-set on using the JVM, which has a
             | lot of pros.
             | 
             | For most people Python/Javascript also does the job and you
             | don't need to learn another paradigm -- a Lisp -- to code
             | for it, which also makes sense.
             | 
             | However, learning a Lisp also makes you a better coder
             | because of immutability and less side-effects. Hence why
             | Clojure is still around.
        
               | diggan wrote:
               | > For most people Python/Javascript also does the job
               | 
               | True, and people should use whatever works best for
               | them/for the job, no questions asked.
               | 
               | But they also have nowhere near the same experience even
               | though they technically have REPLs. The way a JS/Python
               | dev typically use a REPL is experiment in the REPL
               | itself, then when happy, write the "real code", while a
               | Clojure developers write "real code" all the code,
               | sending selections of code to a REPL in the background,
               | viewing the results in their editor, and just saves the
               | file when they're happy. It might sound similar, but very
               | different experience.
               | 
               | > However, learning a Lisp also makes you a better coder
               | because of immutability and less side-effects. Hence why
               | Clojure is still around.
               | 
               | I don't think "immutability" and "less side-effects" is
               | something lisps in general/all lisps promote/facilitate,
               | it's mostly a thing that Clojure (and children) sticks
               | out for caring a lot about. Scheme/Common Lisp is about
               | as immutable as JavaScript is, and lots of CL
               | programs/code out there spreading mutation all over the
               | place, while in Clojure it's pretty common to just have
               | small "pieces" of mutation in somewhat centralized
               | location.
        
               | cess11 wrote:
               | I think it's "around" because it's quite productive and
               | sits on a rock-solid runtime with support for an
               | astonishing amount of libraries.
               | 
               | Around these parts it's common to have read and
               | appreciated Paul Graham's old writings about becoming a
               | better software developer through Lisp, and that would be
               | Common Lisp, i.e. very mutable, commonly object oriented.
        
               | cogman10 wrote:
               | > learning a Lisp also makes you a better coder
               | 
               | It can do, but it also can make you a worse coder.
               | Specifically in typed languages.
               | 
               | One of the issues I've ran into with Clojure devs doing
               | Java is that instead of relying on a type, they tend to
               | want to write stuff like `Map<String, Map<String,
               | Object>>`. Even when the key sets in both maps are well
               | known.
               | 
               | This becomes worse when you mix that with Immutability.
               | Immutability can be fine except when you need a mutation.
               | In applications that require heavy mutation of data a
               | `Map<String, Map<String, Object>>` is one of the worst
               | ways to represent structured data, copying that structure
               | is EXTREMELY expensive.
               | 
               | This isn't to say that you shouldn't usually strongly
               | prefer Immutability. But it's also to say you shouldn't
               | underestimate the cost of allocations and copying data.
               | 
               | Theres always tradeoffs. Part of being a good programmer
               | is knowing when those tradeoffs are best applied.
        
           | daslu wrote:
           | One important detail is that in Lisps like Clojure, printed
           | values can usually be read back as code. So, the REPL is
           | really a read-eval-print-LOOP.
           | 
           | Another detail is that the whole culture of the language,
           | oriented towards immutable data, makes it very easy to
           | evaluate almost any sub-expression in your code, which makes
           | the whole code introspectable in a very playful and dynamic
           | way.
        
             | dionian wrote:
             | I never got deep into any lisp like language but this was
             | one of my favorite aspects of them - homoiconicity.
        
         | xigoi wrote:
         | > Things you don't like can generally be fixed (at least
         | locally) using macros and libraries.
         | 
         | What macro do I use to make it not run on the JVM? :)
        
           | erichocean wrote:
           | That's one of it's best features!
           | 
           | But it runs on other things--Microsoft's CLR, Dart's runtime,
           | JavaScript's runtime, Erlang's runtime, and with Jank, on top
           | of LLVM.
        
         | barrenko wrote:
         | "...not as clumsy or random as AI, an elegant weapon from a
         | more civilized age."
        
         | nogridbag wrote:
         | I gave Clojure a shot some years ago and even wrote an
         | important tool used daily by all employees at our company in
         | Clojure. The problem for me was maintenance. If I had to make
         | any change to that code, I had to dive into the REPL just to
         | understand it. Whereas with something like Java, even if
         | something is poorly written and not documented, I can get at
         | least a minimum understanding of the code just looking at the
         | types.
         | 
         | I've been working on a large modern Java application lately and
         | have never really felt the need for a REPL workflow even after
         | having been exposed to it in Clojure. I tend to structure my
         | Java code so it can be easily unit-testable and then just run
         | the suite of unit tests (several thousand) in a few seconds as
         | needed.
        
           | nathan_compton wrote:
           | What about core.typed. I find gradual type systems to be hard
           | to work with for some reason.
        
       | lemper wrote:
       | > Positive self selection for hiring candidates
       | 
       | > "But what about hiring?" When you use any language that isn't
       | in the top 3 of currently most popular languages, you will get
       | this question. JavaScript programmers are counted in the
       | millions, Clojure programmers in the tens of thousands. How will
       | you ever find the required talent?
       | 
       | is it just me or i, for the love of whatever that is holy, find
       | that fp related jobs are so few and far in between? not only
       | clojure, but also f#, haskell, etc? to be honest, fam, if you
       | want to sell a language or two, at least make it possible for
       | people to make a living in it. sorry to say, mate, but my kids
       | can't eat a "lovely" niche programming language.
       | 
       | p.s., i actually have some working exp. in haskell yet nobody
       | approached me because of it.
        
       | DeathArrow wrote:
       | As I skimmed trough the article, the most important pros of
       | Clojure seem to be: REPL, functional language, immutable data,
       | dynamic typing.
       | 
       | I wonder what would happen if someone adds a REPL to F#. Sure, it
       | wouldn't have dynamic typing, but isn't static typing good for
       | large code bases?
       | 
       | In particular, judging from the article and comments, it seems
       | that the major boon is having an REPL integrated in the IDE,
       | running in the background, so you can have feedback while you are
       | writing the code.
       | 
       | Having such an integrated REPL for a language like Python would
       | make the productivity up to par with Clojure?
       | 
       | I am trying to understand if Clojure has a particular feature
       | other languages can't add with ease.
        
         | fhd2 wrote:
         | I use Python with a REPL in Emacs, it's relatively similar. The
         | two important differences to Lisps I see:
         | 
         | 1. Syntax. It's a bit easier to just evaluate a symbolic
         | expression (put in a simplified manner: anything enclosed by
         | parentheses) than to select a region of Python code to
         | evaluate. But it's no major issue. Don't know about any syntax
         | that has similar properties, Ruby seems to be somewhat similar
         | in spirit, every expression returning an object. Python OTOH
         | has all kinds of constructs you can't evaluate readily.
         | 
         | 2. Functional code. Lisp code is generally largely side effect
         | free, Python is not. That goes from the libraries down to how
         | you write your own code by convention. Evaluating code without
         | side effects for quick feedback is a breeze. For side effect
         | riddled code, it's kinda easier to just use unit tests with
         | mocks etc. for that. There are lots of languages with good
         | functional libraries nowadays.
         | 
         | Generally speaking, the things you list are what used to be
         | unique about Lisp. But apart from the two points I'm making, I
         | don't believe that's the case anymore. Lots of languages got
         | inspired in the last few decades. I love Lisps and I wish I
         | could use them more, but I'm happy lots of popular languages
         | got reasonably close.
        
         | neonsunset wrote:
         | > I wonder what would happen if someone adds a REPL to F#
         | 
         | F# does, in fact, have REPL and excellent one at that!
         | 
         | There is F# interactive and F# scripting. It's my workhorse for
         | all sorts of automation and quick "analyze data and draw a
         | chart" style of one-off scripts. It's vastly superior
         | experience because when editing F# scripts you get full LSP,
         | ability to reference nuget packages without vendoring anything,
         | etc etc.
         | 
         | Gradual typing and full type inference make it look at times
         | like dynamically typed language but it's anything but and gives
         | really nice user experience.
         | 
         | https://learn.microsoft.com/en-us/dotnet/fsharp/tools/fsharp...
        
         | globular-toast wrote:
         | The main problem with other languages is they are not designed
         | from the ground up to be REPL driven. With Python, for example,
         | it works fine until you have more than one module, then it just
         | falls apart completely. With Lisps like Common Lisp and Clojure
         | you never have to reload the REPL for any reason. You program
         | is running "live". It's really hard to describe, to be honest,
         | you just have to try a true REPL language like (CL is the best,
         | but Clojure is pretty good too).
        
       | vim-guru wrote:
       | I've been working with Clojure on and off for over a decade, and
       | I've found it exceptionally efficient at solving a wide range of
       | problems--making it one of the best general-purpose languages
       | available. However, I sometimes envy the capabilities of OTP,
       | which provides a straightforward way to build fault-tolerant
       | servers without the overhead of managing containers or databases.
       | 
       | Additionally, while the growing number of compile targets in the
       | Clojure ecosystem is impressive, it can also create confusion for
       | newcomers. Whether it's compiling to native code with Jank,
       | generating quick script snippets with Babashka, or using subsets
       | of ClojureScript like sci or cherry, the diversity is both a
       | strength and a challenge. I believe a concerted effort to unify
       | configurations across these targets would help streamline the
       | ecosystem and make it easier for developers to choose the right
       | tool for their needs.
        
         | aquariusDue wrote:
         | I too am excited about Jank but I thought it wasn't even hobby
         | project ready yet?
         | 
         | Also yeah, I agree that Babashka is a delight. I've been using
         | it to manage a Caddy server via Caddy's JSON API and it worked
         | great, super flexible.
        
       | hewrin wrote:
       | I would have loved to continue working in Clojure but the jobs
       | just aren't there. I spent 2 years trying to get a job and and
       | couldn't even get an interview. 2 weeks of Ruby on Rails
       | searching got me 2 interviews.
        
         | clusterhacks wrote:
         | Similar experience.
         | 
         | I now think of Clojure as a power tool for small shops and
         | consultants. These aren't the kind of places that typically
         | cast a wide net looking for "employees." Most of the
         | opportunities are maybe more focused on proving that you can
         | bring in business and network effectively enough to be a known
         | quantity in the Clojure community.
        
       | tobyhinloopen wrote:
       | How do people feel about Clojure on the client? (Javascript
       | replacement)
        
       | rrgok wrote:
       | I would like to learn ClojureScript for webapp development with
       | react. But, in 2025, I don't know how to get started. In 2024 I
       | had the same problem. Lein, Shadow, Deps? What do I have to use?
       | How do I get started with REPL driven development? Any in depth
       | video-tutorials on how to take advantage of nREPL in 2025? If I
       | want to use React, how to use third-party packages? Should I use
       | reframe, fulcro, or retit with ohm? Everytime I try to start I
       | give up because the ecosystem is confusing. What is the right
       | way? And if I want to develop in clojure fullstack (frontend and
       | backend both in clojure/script), what is battletested approach?
       | 
       | Oh well, I forgot: how to use with TailwindCSS 4? What
       | incantation of build system do I have to configure for live-
       | reloading when classNames changes?
       | 
       | Sorry for the rambling. Just a poor confused user.
        
         | yogsototh wrote:
         | One part of the joy that came with using Clojure is that there
         | isn't really any bad choice. For example, I wanted a quick and
         | dirty internal web application for admin purposes. I went with
         | reframe. Why? Because I wanted to try it. And I knew, that I
         | could get things done with it.
         | 
         | This is probably not the easiest "framework" (not sure this is
         | a good name for it) but it was very fun. I think, if I had to
         | progress from just a toy to a really strong, user facing UI, I
         | think it would still be a pretty good choice. If some feature
         | is missing, or something doesn't work as I would have liked, I
         | know it will not be difficult to correct it myself.
         | 
         | I know that this could feel overwhelming, but this is freedom
         | in a world where you expect there exists a single "best
         | practice". As long as the tool is powerful enough it will be
         | fine. On my end, I appreciate the fact there is not a single
         | "web framework" in Clojure. Instead you have tons of libs you
         | can use that work well together because they are all tied with
         | a few common concepts (like ring for example). If you don't
         | like to choose the libs. There are a few people that provide a
         | starter pack with somewhat nice bundle of libs in a single
         | system like pedestal or luminus for only citing two of them.
         | 
         | My recommendation is to not lose too much time looking for the
         | best choice. Most of them will be good.
        
       | ddmichael wrote:
       | Yawn.
        
       | nokun7 wrote:
       | I recall when I used to work for Pupper Labs - then PuppetDB
       | jumping to Clojure in 2012 was a gutsy call that totally paid off
       | and put the language on the map. Puppet was a Ruby shop, but as
       | data piled up, they needed something really cool and risky--enter
       | Clojure, which we though was a slick Lisp running on the JVM. It
       | turned PuppetDB into a beast for storing catalogs and reports,
       | leaving Ruby's old setup in the dust with crazy speed boosts,
       | like 130 times faster for some tasks, thanks to its async magic
       | and functional vibe. We could've gone Java or JRuby, but
       | Clojure's concise code and JVM power hit the sweet spot, making
       | PuppetDB a lean, scalable backbone for thousands of nodes. It
       | wasn't just a tech switch--it showed Clojure could hang with the
       | big dogs, influencing Puppet's later projects and proving a niche
       | language could rock real-world infrastructure. It was the best
       | move and kept thing really interesting - in a good way of course.
        
       | dartos wrote:
       | Is the elixir+erlang ecosystem less stable than clojure's
        
       | slifin wrote:
       | If you are using Clojure please look at this:
       | 
       | https://www.flow-storm.org/
       | 
       | If you can get past the serviceable UI then it's coding nirvana
       | literally looking inside the program
       | 
       | Pair that with a good test suite so you can trigger lots of
       | different scenarios and you're in heaven
        
       | rjinman wrote:
       | Couldn't agree more with the necessity for fast feedback loops.
       | I've experienced the opposite, and it's not fun.
       | 
       | I worked with Clojure/ClojureScript (mostly ClojureScript) for a
       | couple of years many years ago. It was the first time I'd worked
       | professionally with a functional language, so I made a game of
       | minesweeper in my free time to help get to grips with it:
       | https://github.com/robjinman/cljsmines
       | 
       | Back then, I fully bought into the idea that functional language
       | like Clojure were the future, especially on the web. The way
       | application state is managed is perhaps the key virtue of
       | functional programming - if you get it right, you can design your
       | program to consist mostly of completely pure functions. I
       | remember how enlightening that was once I understood it.
        
       | dotemacs wrote:
       | Somebody brought up a point about outdated documentation.
       | 
       | Currently https://clojuredocs.org is sort of the go to place. It
       | wins due to Google algorithm.
       | 
       | I wanted to add the ability to vote on answers provided there. So
       | that you have the ability to see the most relevant/popular
       | answer, rather than the oldest.
       | 
       | Raised an issue on the repo, four years ago now. No response:
       | 
       | https://github.com/zk/clojuredocs/issues/222
       | 
       | And why do I mention Google algorithm? Because there was another
       | effort that tried to create a (debatably) nicer documentation,
       | but due to lack of Google traffic, it died. See:
       | https://news.ycombinator.com/item?id=8027119
       | 
       | For a more eloquent argument on its uses, see this blog post:
       | 
       | https://metaredux.com/posts/2019/06/29/farewell-grimoire.htm...
        
       ___________________________________________________________________
       (page generated 2025-02-24 23:01 UTC)