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