dotemacs 16 minutes ago

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...

hlship 15 hours ago

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.

  • nogridbag 27 minutes ago

    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.

  • xigoi 4 hours ago

    > 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 3 hours ago

      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.

  • Byamarro 5 hours ago

    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.

    • daslu 4 hours ago

      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 4 hours ago

        I never got deep into any lisp like language but this was one of my favorite aspects of them - homoiconicity.

    • cess11 4 hours ago

      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.

      • snarkyturtle 3 hours ago

        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 37 minutes ago

          > 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.

      • dmos62 4 hours ago

        You can eval strings in Javascript, so pretty sure that's possible.

        • cess11 4 hours ago

          Looking around I don't find any maintained projects for this purpose.

          • stronglikedan 2 hours ago

            It's just a native function named eval(), so I wouldn't expect to find projects built up around it.

  • rootnod3 14 hours ago

    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 4 hours ago

      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 2 hours ago

        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.

  • pjmlp 8 hours ago

    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.

  • gavmor 14 hours ago

    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 13 hours ago

      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.

      • lkitching 6 hours ago

        Neither defprotocol nor deftype introduce static typing into Clojure. Errors in their usage are not checked statically and are only discovered at runtime.

        • huahaiy an hour ago

          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.

        • rrgok 4 hours ago

          So what happens at runtime if errors are found?

          • synthc 3 hours ago

            you get runtime errors with a long JVM stacktrace

            • erichocean 3 hours ago

              If you paste into Claude, it will instantly tell you what's going on.

      • ndr 8 hours ago

        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.

    • eigenhombre 13 hours ago

      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 à la carte strictness in the language via Spec, Malli, structured types, etc.

      • hhhAndrew 9 hours ago

        > 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 4 hours ago

          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.

  • eddd-ddde 14 hours ago

    How does the REPL approach scale in very large codebases? I.e. code that talks to multiple services, complex configurations, etc..

    • huahaiy 13 hours ago

      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 13 hours ago

      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

    • thom 8 hours ago

      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.

    • ludston 9 hours ago

      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.

  • barrenko 2 hours ago

    "...not as clumsy or random as AI, an elegant weapon from a more civilized age."

slifin 2 hours ago

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

iLemming 15 hours ago

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!"

  • gloomyday 11 hours ago

    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)...

  • rendaw 5 hours ago

    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

  • regularmother 8 hours ago

    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?

    • doall 5 hours ago

      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 2 hours ago

        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.

    • cardanome 6 hours ago

      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

  • golly_ned 13 hours ago

    I've never seen anything but praise for clojure.

    • ldite 8 hours ago

      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 6 hours ago

        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 4 hours ago

          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 3 hours ago

            > 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

            • hombre_fatal 2 hours ago

              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.

            • maleldil 3 hours ago

              That's a lot of different tools for something that could simply be a statically defined type with compile-time checking.

    • iLemming 13 hours ago

      > 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 12 hours ago

      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.

    • ddellacosta 3 hours ago

      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

    • sundarurfriend 9 hours ago

      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".

      • maleldil 3 hours ago

        Add "dynamic language" in this day and age where everyone thinks static languages are cool again.

      • worthless-trash 4 hours ago

        My new favourite is am seeing is clojure doesnt have enough syntactic sugar.

        SMH.

  • j45 15 hours ago

    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.

rjinman 29 minutes ago

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.

d_t_w 18 hours ago

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...

jwr 17 hours ago

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 cliché 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 an hour ago

    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 17 hours ago

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 16 hours ago

    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

    • noodletheworld 16 hours ago

      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 12 hours ago

        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

        • harperlee 8 hours ago

          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.

        • mrkeen 9 hours ago

          I don't know enough about protocols. Will the compiler stop you if you misuse them?

          • serpix 7 hours ago

            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 4 hours ago

              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

    • MarkMarine 14 hours ago

      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 11 hours ago

        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 9 hours ago

          Not necessarily a permutation; e.g.

              f :: [a] -> [a]
              f [] = []
              f (x:xs) = x: x: f xs
    • rednafi 16 hours ago

      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 16 hours ago

        In what way is clojure.spec similar to python's type hints? O_o

  • kamaal 11 hours ago

    >>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.

phtrivier 19 hours ago

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 19 hours ago

    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 17 hours ago

      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 15 hours ago

        What language ecosystem does this right?

        • asa400 14 hours ago

          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.

  • delegate 4 hours ago

    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 4 hours ago

      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 3 hours ago

        Ain't nothing wrong with Swing or JavaFX :).

  • jwr 17 hours ago

    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.

  • saghm 18 hours ago

    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

    • hlship 15 hours ago

      ~ > 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).

    • Capricorn2481 17 hours ago

      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.

  • jayceedenton 18 hours ago

    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 15 hours ago

      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 11 hours ago

        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 13 hours ago

      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.

  • eduction 15 hours ago

    > 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 5 hours ago

      > 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 4 hours ago

        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.

ilrwbwrkhv 20 hours ago

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.

  • kubb 20 hours ago

    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.

    • lispisok 19 hours ago

      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.

      • kubb 10 hours ago

        I think Go, for all its flaws, is an example of a language where mediocre developers can be more successful.

        Java would be another.

      • travisgriggs 17 hours ago

        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.

    • ilrwbwrkhv 18 hours ago

      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 16 hours ago

      You could replace Clojure with Python or Perl, and this Would honestly be even more true.

    • jb1991 20 hours ago

      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.

  • anonzzzies 18 hours ago

    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 18 hours ago

      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 10 hours ago

        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 17 hours ago

    Why did you move away from go? I don't use it, but seems like productive language, being simple, fast to compile and performant.

    • MarkMarine 14 hours ago

      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 8 hours ago

      > 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.

    • ilrwbwrkhv 15 hours ago

      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.

  • giancarlostoro 20 hours ago

    > 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 20 hours ago

      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?

      • sodapopcan 16 hours ago

        > 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 an hour ago

          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

      • codr7 20 hours ago

        The condition framework/break loop is one thing I wish more Lisps would copy.

        • ilrwbwrkhv 15 hours ago

          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 11 hours ago

            Makes the REPL feel a lot more alive and interactive, much like a SmallTalk IDE.

      • zelphirkalt 20 hours ago

        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 16 hours ago

          For starters, those identifiers aren't bound until the function actually runs.

  • oDot 19 hours ago

    You should give Gleam a shot. No REPL, but its simplicity, functional-ity and the BEAM lend themselves to the get-shit-done approach

    • ndr 18 hours ago

      Immutable data and REPL is where is at for iteration speed though.

    • ilrwbwrkhv 18 hours ago

      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 13 hours ago

        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 10 hours ago

        > Gleam takes more code to write than rust.

        Do you have some source for that? Perhaps an example?

  • agumonkey 18 hours ago

    Can you describe your stack and workflow ?

dustingetz 19 hours ago

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 37 minutes ago

    As someone who worked with Common Lisp many moons ago, this is the answer I needed to pique my interest in Clojure (again).

MarkMarine 20 hours ago

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 9 hours ago

    >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 3 hours ago

      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.

nbittich 20 hours ago

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

  • fiddlerwoaroof 19 hours ago

    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

  • gleenn 19 hours ago

    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.

  • kccqzy 19 hours ago

    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.

jrsj 21 hours ago

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)

viccis 19 hours ago

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.

  • delegate 4 hours ago

    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..

  • iLemming 15 hours ago

    > 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 8 hours ago

      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 7 hours ago

      What was it about Elixir that you found dissatisfactory? I am currently evaluating Clojure vs. Elixir for a new project.

      • innocentoldguy 7 hours ago

        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 3 hours ago

          If you want lisp on beam there is always lfe .

  • dankwizard 13 hours ago

    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 12 hours ago

      I'm curious, how did you form this opinion? Did you have a bad experience with Clojure yourself?

rrgok 4 hours ago

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 3 hours ago

    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.

hewrin 7 hours ago

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 44 minutes ago

    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.

ampunix1337 20 hours ago

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 20 hours ago

    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 17 hours ago

      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 17 hours ago

        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 16 hours ago

          Looks like you're right! I stand corrected, it's admittedly been a few months since I've touched Clojure.

          • newlisp 15 hours ago

            You were not wrong though, Java 8 was released in 2014, so it only took them ~10 years ;)

            • tombert 15 hours ago

              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 11 hours ago

      > 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.

  • lukev 18 hours ago

    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.

  • yogthos 20 hours ago

    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.

moomin 18 hours ago

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 17 hours ago

    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.

    • kunley 8 hours ago

      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.

    • rednafi 16 hours ago

      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 14 hours ago

        > 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 13 hours ago

        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?)

    • fud101 3 hours ago

      The only counter argument that matters to me is there are hardly any jobs.

vim-guru 9 hours ago

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 7 hours ago

    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.

DeathArrow 10 hours ago

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 9 hours ago

    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 5 hours ago

    > 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...

codr7 20 hours ago

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

  • cellularmitosis 19 hours ago

    Macros being supported via quoted arguments is clever

    • codr7 17 hours ago

      Thank you, I'm very pleased with that detail :)

  • thom 19 hours ago

    What wall did you hit? I can jump into a Clojure REPL without needing a project or even any files.

    • codr7 17 hours ago

      The opinions on data and programming in general-wall.

      Not bad ideas, just not the kind I like shoved down my throat.

dartos 3 hours ago

Is the elixir+erlang ecosystem less stable than clojure’s

tobyhinloopen 4 hours ago

How do people feel about Clojure on the client? (Javascript replacement)

newlisp 19 hours ago

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 17 hours ago

    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 16 hours ago

      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 14 hours ago

        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 14 hours ago

        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.

kstrauser 17 hours ago

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 17 hours ago

    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 11 hours ago

      Ah, got it. So it’s not to much that Scala went away, as that Java became Scala?

      • valenterry 8 hours ago

        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.

  • KingMob 10 hours ago

    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 8 hours ago

    I'd say most of its niches (async with Futures, akka, spark) now have other options. Also, Scala 3 happened.

nokun7 3 hours ago

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.

jasebell 18 hours ago

Done me fine for the last decade. Along with all the other languages that kept me in employment. I still use it daily.

patcon 15 hours ago

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.

  • lukev 15 hours ago

    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.

    • patcon 10 hours ago

      > 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 :)

    • KingMob 11 hours ago

      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.

  • neillyons 5 hours ago

    > 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

  • eduction 15 hours ago

    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?

  • j45 15 hours ago

    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 10 hours ago

      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 28 minutes ago

        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.

fithisux 2 days ago

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.

fernirello 18 hours ago

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.

lemper 13 hours ago

> 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.

moi2388 21 hours ago

Because you want the type safety of lisp with the simplicity of the jvm /s

  • gleenn 21 hours ago

    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!

    • synthc 20 hours ago

      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.

    • AnimalMuppet 20 hours ago

      > 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 19 hours ago

        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 19 hours ago

          > 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 18 hours ago

            Or you need a REPL that lets you poke at the living code. It's just different.

            • Capricorn2481 16 hours ago

              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 14 hours ago

                > 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 12 hours ago

                  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.

  • yogthos 20 hours ago

    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 14 hours ago

      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 13 hours ago

        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 13 hours ago

          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 7 hours ago

            > 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 5 hours ago

              The part of code not compiling got me interested. Do you happen to have an example or tutorial about this?

          • yogthos 3 hours ago

            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 34 minutes ago

              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.

  • iLemming 13 hours ago

    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 10 hours ago

      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.