News for hackers. Stuff that matters.
Re:Why is Jepsen written in Clojure? by jwr on Wednesday December 06, 2023 @02:57AM (#38541475)
As a heavy user of Clojure (my SaaS is written in Clojure/ClojureScript) for 10 years or so, I would fully agree with what Kyle wrote. In addition, things that I found very valuable:

* most of my domain code is in cljc files, so these get compiled both server-side and client-side and I get a huge boost from that

* transducers and transducer pipelines are an under-appreciated feature, I get huge mileage out of them, because of performance, composability and reusability

* stability and longevity: Clojure was created by a very experienced system designer and programmer (Rich Hickey) and it shows. Backwards compatibility is hugely important, and I can focus on my application rather than rely on tools that are a moving target. It's not an accident that an average "Clojure programmer" (I dislike these kinds of tags, but let's run with it here) has 12+ years of experience and earns a salary in the top quartile at least.

Re:Why is Jepsen written in Clojure? by drikerf on Wednesday December 06, 2023 @03:26AM (#38541635)
Similar story. I'm also running my SaaS on Clojure and maintenance has been a dream compared to other languages. Things rarely break and are easy to upgrade.

Developer experience is fantastic too with HMR, REPL and cljc files. It's fun to write Clojure code :)

Re:Why is Jepsen written in Clojure? by weikju on Wednesday December 06, 2023 @04:41AM (#38542040)
HMR?
Re:Why is Jepsen written in Clojure? by G4BB3R on Wednesday December 06, 2023 @04:47AM (#38542075)
"Hot Module Replacement (HMR) is a feature in some programming languages and frameworks that allows developers to update modules or parts of the application in real-time while the application is running, without requiring a full page refresh. This is particularly useful during development as it speeds up the development process and helps maintain the application state."
Re:Why is Jepsen written in Clojure? by weikju on Wednesday December 06, 2023 @05:53AM (#38542377)
Hmm I’d rather hear more from the GP (assuming it’s the same concept) and specific tools being used than a generic GPT sounding reply. Thanks though at least I learned an acronym (no snark).
Re:Why is Jepsen written in Clojure? by monsieurbanana on Wednesday December 06, 2023 @07:51AM (#38543180)
I can't blame you for thinking it was a GPT reply these days. Anyway I'm also not GGP but he's right, it is Hot Module Replacement.

You don't really need specific tools for HMR in clojure, it's kind of baked in the language thanks to:

- immutability (not impossible but hard to do HMR without it)

- REPL workflow

When developing on clojure, there's a long-lived clojure process and you continually send expressions to be evaluated there.

Let's say you start a server, you make a change to one of the functions that handle a route, just after making the change you will evaluate that function (from your editor) and the update will be "live" in the running server.

It's honestly hard to describe and it doesn't help that we call that "repl-based workflow" when in fact we are not using the REPL directly, but rather through plugins available for various editors. People might think it's the same as using nodejs or python repl, when it's nothing like that. If you're interested, you could check "Parens of the Death" or look for "Clojure CALVA" (VSCode's clojure plugin) videos on youtube.

https://www.parens-of-the-dead.com/s2e1.html

Edit: It is also not limited to development. Nothing prevents you from hooking into the clojure process in your prod server from your editor, editing a function and evaluating it.

You just monkey-patched a live server to fix a time-critical bug with roughly the same workflow as editing your code locally. Or brought production down, 50/50, but what's life without some risks eh?

Re:Why is Jepsen written in Clojure? by 38529977thrw on Wednesday December 06, 2023 @09:07AM (#38544047)
Just for the record, in Java (JVM) this is done (routinely circa first 'bean containers' of ancient history) via interfaces and class loaders. Using Java I can have n distinct versions of a class each implementing the same interface in the same process as long it is the interface reference that is passed around.

> immutability

Make a case for immutability being so critical to HMR. How does an immutable data allow for swapping of code.

Re:Why is Jepsen written in Clojure? by groestl on Wednesday December 06, 2023 @09:38AM (#38544442)
AFAIK, Java's native HMR is not built on dynamic classloaders, but using a separate technology built into the JVMs debugger support, called HotSwap. You can only replace (certain) function bodies with it. To get around these restrictions, more elaborate HMR can be achieved with classloader magic, such as OSGi, but you subscribe to a world of ClassCastException-pain with it.
Re:Why is Jepsen written in Clojure? by kaba0 on Thursday December 07, 2023 @08:53AM (#38556260)
It is still a very good system, and you can get quite a far away with only method-swaps, I love to use them in case of Spring apps, where changing a backend controller and doing another api call is a very fast REPL cycle basically.

But objects don’t give themselves very easily to hot reloading, there are a bunch of edge cases that are not well-defined in a semi-swapped state (e.g. this new field always gets a value in the constructor, but was no just added. Should you rerun the constructor, or have it be in an inconsistent state?)

Immutable/FP concepts are a much better fit, especially if the building blocks are as small as they are in case of Clojure.

Re:Why is Jepsen written in Clojure? by everforward on Wednesday December 06, 2023 @04:27PM (#38549703)
My limited understanding of Clojure's HMR is that there aren't n distinct versions of a class/function. It's actually removing the old ones from memory and replacing them.

Also, it is worth noting that everything is immutable, not just data. Functions/protocols/records/etc are also immutable.

Functions/classes being immutable makes it much, much easier to reason about the dependencies of that function/class. E.g. check out this Python code:

    import someotherpackage
    import threading
    import random

    class MyLogger:
        def __init__(self, name, path):
            self.path = path
            self.name = name
        def log(self, message):
            with open(self.path, 'w') as fd:
                fd.write(message)

    my_logger = MyLogger("init-logger", "init.log")
    someotherpackage.logger = my_logger
    someotherpackage.logger.error = print

    print = someotherpackage.logger.error
    my_logger.thingy = "thingy"

    def change_logger():
        def actually_do_change():
            time.sleep(random.randint(1, 100000))
            new_logger = MyLogger("main-logger", "main.log")
            someotherpackage.logger = new_logger
            someotherpackage.logger.error = my_logger.error
        time.sleep(random.randint(1, 10000))
        threading.Thread(target=actually_do_change).start()

    time.sleep(random.randint(1, 10))
    threading.Thread(target=change_logger).start()
Now imagine that this isn't our `main`, this is some library that's a transitive dependency of something we're importing.

Trying to hot-swap this would be awful. The big issues related to mutations are that a) there's no indication in someotherpackage that it's behavior depends on this package, and b) because mutations are allowed, the order that things are reloaded in matters, and c) some mutations are time-bounded.

If I change MyLogger and the VM/interpreter wants to hot-swap MyLogger, it has to recognize that it can't just re-load the instances of MyLogger with the same state. It has to re-load those instances, then re-mutate them, then re-mutate someotherpackage, and finally re-mutate the print function. It might also need to do the stuff that's delayed by that thread. Maybe. Depends on a couple of random integers that probably got GCed a while ago.

If you want to add an extreme layer of annoying, consider that this package could be a late import and only happens if a plugin is enabled, so the earlier code might rely on `print` actually being `print` or on someotherpackage.logger behavior that changes over time.

None of that applies in an immutable world. Nothing can mutate the someotherpackage package nor the `print` function, ergo nothing can depend on an earlier or different version of them. Dependencies are easy to track because the only way to introduce them is to import/directly reference them, or have them passed as parameters.

I don't know that it even needs any dependency tracking, though (provided they're using a pointer to a pointer, or maybe something smarter than that I can't think of). Immutability means that a) everything can be passed as pointers safely, b) those pointers can't be modified by the code, and c) there is never a reason to have more than one copy of a pointer to the bytecode for a function.

Each function gets a pointer to its bytecode, let's call that p1. Every reference to that function is a pointer to p1, which we'll call p2.

When you want to hot-swap code the language pauses the VM/interpreter, recompiles any function with a diff (easy with an AST), puts the new functions in memory somewhere new, changes p1 to point to the new bytecode, then marks the old bytecode for GC.

If you tried something that simple in Python for the code I wrote above, it would explode. It's an infinitely harder problem.

> Using Java I can have n distinct versions of a class each implementing the same interface in the same process as long it is the interface reference that is passed around.

It's been a while since I worked with those app containers, but from my recollection it shares virtually nothing with hot reloading. E.g. is state preserved between those? If I'm caching stuff in RAM, and I change that class out, does it keep the cache? HMR does, as I recall.

My understanding is that app containers basically just run N versions of your app/class and allow you to choose which one you route execution to.

App containers are more similar to blue-green deployments with a load balancer. Each instance is totally separate, and the load balancer lets you choose which one you route to. App containers just do that process inside the JVM.

That's not bad, but it's also not as good as being able to repeatedly tweak a function without ever clearing caches or re-connect to downstreams or etc.

Re:Why is Jepsen written in Clojure? by roenxi on Thursday December 07, 2023 @06:18AM (#38555186)
> My limited understanding of Clojure's HMR is that there aren't n distinct versions of a class/function. It's actually removing the old ones from memory and replacing them.

It is almost both. Clojure creates n distinct versions of the function (which are in fact objects and subject to garbage collection). The symbol of the function is rebound (technically this language is wrong) to point to the most recent one. Then, usually, the Java garbage collector deletes the old object.

So it is possible (likely under some code styles) that old versions of a function can hang around in a REPL environment if they ended up embedded in a data structure. However, if you make the call by resolving the function's symbol then that will reliably call the most recently def-ed version.

For example:

(defn poor-style [] 1)

(def object {:fn poor-style :call (fn [] (poor-style))})

(defn poor-style [] 2)

(prn ((:fn object))) ; => 1, calls the old embedded function

(prn ((:call object))) ; => 2, calls a function that resolves the symbol, finds the new version.

(prn (poor-style)) ;=> 2, just call the new function

Re:Why is Jepsen written in Clojure? by beepbooptheory on Wednesday December 06, 2023 @11:17AM (#38545894)
I have a lot more experience with common lisp, but currently doing AOC with Clojure right now to try and position myself better for my dream job where I can work with any kind of lisp. Thought I could maybe ask a quick question I have been having trouble answering? I find that with emacs/cider any evaluation is blocking. I am a little spoiled on SLIME/SLY, where it has the nice baked-in feature that any evaluation you do interactively becomes its own process and you can carry on evaluating other things if the process is long running. Is there any way I can replicate this in clojure? Is it just a matter of using `future` explicitly? Or is there something I am missing with cider?
Re:Why is Jepsen written in Clojure? by Volundr on Wednesday December 06, 2023 @12:51PM (#38547230)
If you want a long running calculation to not block the REPL you'd need to use a future, or some other method to get it off the REPL thread.

I don't remember what your describing being a feature of SLIME, but it's been 10+ years so I may just not remember.

Re:Why is Jepsen written in Clojure? by monsieurbanana on Thursday December 07, 2023 @05:51AM (#38555046)
I don't think you are missing anything, I am not aware of anything that would automatically launch new threads when evaluating something.

That does seem like an interesting, although in practice I rarely have to evaluate something that would take more than a a couple of seconds, so manually wrapping it in a future seems acceptable.

On a semi-related note, sometimes I mistakenly evaluate something that will take a long time, or there's a bug and I'm stuck in an infinite loop. CIDER has a command to interrupt the on-going evaluation but I'm my experience it only works about half the time. In those cases having it wrapped in a future would certainly be helpful.

Re:Why is Jepsen written in Clojure? by eddtries on Wednesday December 06, 2023 @07:16AM (#38542855)
Fwiw it's a quote from https://webpack.js.org/concepts/hot-module-replacement/, what else would you like to know about HMR?
Re:Why is Jepsen written in Clojure? by PaulHoule on Wednesday December 06, 2023 @09:12AM (#38544114)
It's actually the answer ChatGPT should give, with the citation to back up the quote.
Re:Why is Jepsen written in Clojure? by weikju on Wednesday December 06, 2023 @07:53PM (#38551537)
if only.... lol
Re:Why is Jepsen written in Clojure? by mattsan on Wednesday December 06, 2023 @08:28AM (#38543562)
Have you ever used a dictionary?
Re:Why is Jepsen written in Clojure? by mattsan on Thursday December 07, 2023 @01:31PM (#38559926)
Apologies for the tone. Was really tired when posted.
Re:Why is Jepsen written in Clojure? by travisjungroth on Wednesday December 06, 2023 @12:40PM (#38547075)
If you want better answers, ask better questions.
Re:Why is Jepsen written in Clojure? by weikju on Wednesday December 06, 2023 @07:54PM (#38551543)
Thanks all for the various answers. I guess, coming from common lisp where it's easy to add a new dependency (via asdf / quicklisp) to a running REPL, it's not so easy (yet? until 1.12?) with Clojure. Various utils have been created over the years, so was just wondering if there was something more to the picture that fell under this new term I learned, "HMR"..
Re:Why is Jepsen written in Clojure? by packetlost on Wednesday December 06, 2023 @10:57AM (#38545558)
What do you use for an editor/IDE? I'd love to write more Clojure, but the tooling story is a bit confusing
Re:Why is Jepsen written in Clojure? by Volundr on Wednesday December 06, 2023 @12:47PM (#38547174)
In my case, Emacs+clojure-mode+cider. I'm not sure I recommend learning Emacs at the same time as Clojure though. I usually recommend new users look to Cursive(for IntelliJ) or Calva (vscode) depending on what they are most comfortable with.
Re:Why is Jepsen written in Clojure? by packetlost on Wednesday December 06, 2023 @12:58PM (#38547321)
I'm a vim user and there's no way in hell I'm switching to emacs, even with EVIL mode. I'll check out Calva
Re:Why is Jepsen written in Clojure? by fiddlerwoaroof on Wednesday December 06, 2023 @01:17PM (#38547558)
I forget what the current recommendation for vim is, but back when I still wrote a lot of Clojure, people used vim-fireplace. I think there is a newer one for NeoVim, though
Re:Why is Jepsen written in Clojure? by epiccoleman on Wednesday December 06, 2023 @01:56PM (#38548037)
Almost ten years ago, I gave a lightning talk about Overtone (Clojure mappings for SuperCollider). I used "vim-fireplace" to connect to cider-nrepl and had a pretty good experience being able to quickly eval sexps in Vim.

I'm sure this is wildly outdated by now - I'd be shocked if there wasn't something halfway decent in the NeoVim ecosystem.

I will say, though, that during a brief flirtation with Spacemacs, I absolutely loved the Clojure integration - emacs just feels like it's more "at home" with lisps. Some of the most satisfying programming experiences I've had, honestly.

Re:Why is Jepsen written in Clojure? by cutler on Wednesday December 06, 2023 @06:40PM (#38551005)
As a Vim user I agree. Spacemacs is an excellent Clojure dev environment.
Re:Why is Jepsen written in Clojure? by epiccoleman on Thursday December 07, 2023 @02:42PM (#38560857)
The spacemacs / emacs feature I miss constantly in Vim / VsCode is "slurp/barf" - which is amazing useful in plenty of contexts that aren't s-exps.
Re:Why is Jepsen written in Clojure? by fiddlerwoaroof on Friday December 08, 2023 @04:00PM (#38574322)
Yeah, it’s annoying that paredit is “complected” with Clojure and lisp modes in other editors. This is one of the major things keeping me in emacs: it’s relatively trivial to mash up pre-existing emacs functionality ad hoc; other editors tend to precombine features in arbitrary ways.
Re:Why is Jepsen written in Clojure? by fiddlerwoaroof on Wednesday December 06, 2023 @01:27PM (#38547698)
I too resisted emacs for years while writing Common Lisp in vim, but eventually I ported my vim config line by line to the emacs lisp implementation of the vi standard
Re:Why is Jepsen written in Clojure? by bokchoi on Wednesday December 06, 2023 @02:03PM (#38548119)
Check out Conjure for nvim: https://github.com/Olical/conjure/
Re:Why is Jepsen written in Clojure? by packetlost on Wednesday December 06, 2023 @02:06PM (#38548149)
I'm currently a Conjure (and vim-sexp) user, but was wondering if there was something Clojure specific that didn't also have annoying tabbing defaults
Re:Why is Jepsen written in Clojure? by Volundr on Wednesday December 06, 2023 @01:04PM (#38547402)
Hopefully someone will chime in with their recommended setup for vim. I think there is pretty mature tooling available, but I'm not immediately familiar with it, so my advice there would be no better than Google.

Calva is a solid choice if you don't mind switching editors.

Re:Why is Jepsen written in Clojure? by manishsharan on Wednesday December 06, 2023 @01:26PM (#38547687)
Checkout Cursive on Intellij. The $100 on Cursive is the best $100 I ever spent on a tool.
Re:Why is Jepsen written in Clojure? by wiseowise on Wednesday December 06, 2023 @03:22PM (#38548983)
Author of Cursive is on Hn also.
Re:Why is Jepsen written in Clojure? by drikerf on Wednesday December 06, 2023 @03:38PM (#38549175)
Emacs + CIDER and paredit. Works great!
Re:Why is Jepsen written in Clojure? by DeathArrow on Wednesday December 06, 2023 @04:28AM (#38541955)
Does Clojure have a decent web framework?
Re:Why is Jepsen written in Clojure? by dgb23 on Wednesday December 06, 2023 @07:32AM (#38543002)
Comprehensive frameworks include: biff, kit.

Both of these rely on some of the most popular and simple libraries for web dev.

Most seem to simply use said libraries directly, mix and match what is needed.

If you’re an experienced web developer but new to Clojure, then you’re going to spend a good weekend or so to set up a proper environment, combine the necessary libs and so on, if you have some guidance. The Clojure community is quite welcoming and helpful in that regard.

There’s an initial learning curve, because it’s a functional Lisp though. That comes with some necessary re-wiring, but also with some unique powers.

The cool thing about writing Clojure is that feeling: „Really that’s it?“ when you realize how simple it is. It’s also simply fun to use, because of how interactive it is.

Re:Why is Jepsen written in Clojure? by digdugdirk on Wednesday December 06, 2023 @07:38AM (#38543062)
Do you have any recommendations for good resources for a starting point? And maybe something like a generic "to-do app" style tutorial just to see how everything is laid out and how everything connects?
Re:Why is Jepsen written in Clojure? by dgb23 on Wednesday December 06, 2023 @08:14AM (#38543410)
There are many good tutorials, free and paid books.

However, if you just want to get started and have a minimal thing working without much fuss I recommend this one:

https://clojure-doc.org/articles/tutorials/basic_web_develop...

I haven't directly used it but I reviewed it once and it seems to be one of the most straight forward and carefully written web development tutorials for Clojure. It uses a very minimal set of libraries and it really goes from A to Z. Perfect if you want to just get yourself familiar and have something working.

Re:Why is Jepsen written in Clojure? by digdugdirk on Wednesday December 06, 2023 @11:33PM (#38552851)
Wow. There'll definitely need to be some translation before I understand everything, but you're absolutely right - this tutorial is one of the best I've ever seen.

Thank you for sharing it!

Re:Why is Jepsen written in Clojure? by seancorfield on Friday December 08, 2023 @01:49AM (#38566120)
As the current maintainer of clojure-doc.org, I'd be happy to hear your feedback on what needs additional explanation/clarification.

This year's funding by Clojurists Together allowed me to spend a lot of time completely rewriting large sections of the site to bring it up-to-date with modern Clojure tooling and libraries -- but I know there's still room for improvement.

Re:Why is Jepsen written in Clojure? by digdugdirk on Wednesday December 13, 2023 @10:22PM (#38637408)
Just seeing this now. Very busy with work at the moment to dive into learning a new language/paradigm, but I will honestly set a reminder to check in with you in a few months after I've dug into it some and I'll be sure to take notes with this in mind throughout.

I love the idea of a community investing in this type of outreach (beginner oriented) and I'll be happy to contribute when I can.

Re:Why is Jepsen written in Clojure? by stefcoetzee on Wednesday December 06, 2023 @07:48AM (#38543143)
Consider the tutorial on the Kit website: https://kit-clj.github.io/docs/guestbook.html#guestbook_appl...
Re:Why is Jepsen written in Clojure? by sometimesweenie on Wednesday December 06, 2023 @10:14AM (#38544889)
If you want a solid structure to start with, I’d suggest https://luminusweb.com/ as that’s what I initially learned from. For a todo app I believe the reagent repo has an example of that without the server bits. I could give you some more direction depending on what you’re trying to accomplish
Re:Why is Jepsen written in Clojure? by finnjohnsen2 on Wednesday December 06, 2023 @08:28AM (#38543561)
"No, but maybe" is how I would answer this question myself. Maybe there is a working framework I'm unaware of - but in my experience using Clojure the last few years is that the concept of frameworks is not in the culture of the Clojure community.

You compose your stack of smaller libs and build your own framework so to speak. The right questions in this context are; what http server to use, what routing lib is decent, what is a good lib for my database, what is a good lib for generating html from the server. etc.

If you wanna start using clojure as a web server. Start with 'ring', and you can recieve http requests. You quickly realize you're missing stuff to do what you need and will go searching for libs. You'll find great libs out there for anything you ordinarily need for a web-server setup.

Re:Why is Jepsen written in Clojure? by jwr on Wednesday December 06, 2023 @04:50AM (#38542088)
I am not sure what a web framework is, to be honest. The choices for many parts of a web application are really domain-specific and I'm not sure a single "framework" would work for everyone.

As far as web-related components go, my app uses Rum (as an interface to React), ring, http-kit, pushy (for history manipulation), sente (for websockets), buddy (for authentication tools).

If you are looking for a batteries-included "I want to have some sort of webapp right away" thing, I think https://kit-clj.github.io would fit the bill, but the general feeling in the Clojure community is that unlike Python with Django or Ruby with Rails, the choice of app components is not predetermined by the language.

Re:Why is Jepsen written in Clojure? by spelufo on Wednesday December 06, 2023 @07:21AM (#38542896)
What about the database side of things?
Re:Why is Jepsen written in Clojure? by jetrink on Wednesday December 06, 2023 @08:01AM (#38543264)
If you don't need something as low-level as next.jdbc, HugSQL is my preferred library. It lets you write queries in .sql files, and the queries are then loaded as functions. If you want to dynamically generate queries, there are also libraries like HoneySQL.
Re:Why is Jepsen written in Clojure? by stefcoetzee on Wednesday December 06, 2023 @07:50AM (#38543161)
next.jdbc is the go-to library to interact with SQL databases. https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.3.8...
Re:Why is Jepsen written in Clojure? by simongray on Wednesday December 06, 2023 @03:11PM (#38548867)
Probably worth mentioning that triplestores/Datomic-like databases are relatively mainstream in Clojure: https://github.com/simongray/clojure-graph-resources#datalog
Re:Why is Jepsen written in Clojure? by 22289d on Wednesday December 06, 2023 @06:16AM (#38542507)
> I'm not sure a single "framework" would work for everyone.

I guess you weren't lying because that is not what a web framework is.

If it works for just me, that's a web framework. The fact that there are so many web frameworks shows that none work for everyone.

Re:Why is Jepsen written in Clojure? by shortrounddev2 on Wednesday December 06, 2023 @08:59AM (#38543956)
Components of a web framework:

1. Routing

2. ORM

3. Auth handling

4. Request middleware

5. Templating (if your application requires it)

6. User input validation

Many other components that are escaping me right now

Re:Why is Jepsen written in Clojure? by abc_lisper on Wednesday December 06, 2023 @12:36PM (#38547010)
Most of these are handled by reitit and ring
Re:Why is Jepsen written in Clojure? by WJW on Wednesday December 06, 2023 @10:17AM (#38544934)
Some more standard components I would no longer want to do without in a full-featured framework:

- background job system

- email sending

- translation/localisation

- a decent configuration system suitable for differentiating dev/test/staging/prod/etc, and handling both secret and non-secret values in a sane way

Re:Why is Jepsen written in Clojure? by shortrounddev2 on Wednesday December 06, 2023 @10:54AM (#38545512)
Secret handling has been abstracted away from the framework for everything I worked on; usually our deployment system would mount secrets as a file system and then you read them as a file of key->value pairs. That, or they were just set as environment variables. I guess the framework could provide a standardized secret service, but I usually just write that myself
Re:Why is Jepsen written in Clojure? by WJW on Wednesday December 06, 2023 @11:02AM (#38545647)
> but I usually just write that myself

Not saying you shouldn't, but part of the point of a framework is all the things you don't have to write yourself.

What I like about (say) Rails secret handling is that the secrets file is an encrypted file in the repo itself. This makes it so that you can easily check out and run different versions of the repo from different times and not have to worry about that one time you renamed an envvar or something. Secrets get version controlled together with the app. The autogenerated .gitignore even includes patterns for the key files so you have to go out of your way to check them into the repo. The downside is that merging encrypted files can be a right pain in the arse, for example when two devs added different secrets in different branches.

Re:Why is Jepsen written in Clojure? by shortrounddev2 on Wednesday December 06, 2023 @11:44AM (#38546240)
I feel that web frameworks should be flexible enough that the CI/CD system can put things like secrets into files without worrying about the particular framework that's consuming them. If you don't write the secret service in the web framework, you have to write the secret manager in CI/CD to convert formats or what have you. Something I dislike about spring boot is how spring-y everything has to be.
Re:Why is Jepsen written in Clojure? by ElectricalUnion on Wednesday December 06, 2023 @12:48PM (#38547176)
> CI/CD system can put things like secrets into files

This sounds horrible. Why does specifically your CI/CD need to know those things?

This also sounds like your CI/CD system is "too smart" and your build process is "dumb pipes", what I believe to be a unsupportable, unmaintainable anti-pattern - if people can't build/test things on their own machine, things are likely not repeatable/reproducible at all and you're one CI/CD issue away from losing your project.

> Something I dislike about spring boot is how spring-y everything has to be.

I thought spring "runtime config override" was just dropping a properties (admittedly awful format, latin-1 encoded to boot) file near the compiled project uberjar/war/ear and you're done?

Re:Why is Jepsen written in Clojure? by shortrounddev2 on Wednesday December 06, 2023 @01:11PM (#38547474)
> This sounds horrible. Why does specifically your CI/CD need to know those things?

You set it up so that production secrets are kept in that store and are only accessible by a 1 or 2 high level people. Developers don't have access to production secrets, only dev or staging, which live on their own machines and are lower security risk

> if people can't build/test things on their own machine

I don't see why they wouldn't be able to build/test on their own machine. You just have a different secrets store and keys than the CI/CD does

> I thought spring "runtime config override" was just dropping a properties (admittedly awful format, latin-1 encoded to boot) file near the compiled project uberjar/war/ear and you're done?

Yes I hate this. I want to be able to decide how properties are loaded, not rely on some ethereal state managed behind the scenes and not be able to see if it's loading properly. If I want to use their terrible resources/config file, I'll specify that in middleware/startup

Re:Why is Jepsen written in Clojure? by PaulHoule on Wednesday December 06, 2023 @09:23AM (#38544235)
I think routing makes the minimal viable "framework" -- look at the many systems like Sinatra, JAX-RS, aiohttp, etc where you write functions and supply metadata to tie URLs to functions.
Re:Why is Jepsen written in Clojure? by Capricorn2481 on Wednesday December 06, 2023 @09:57AM (#38544648)
For clojure, that would be biff
Re:Why is Jepsen written in Clojure? by jwr on Thursday December 07, 2023 @05:22AM (#38554875)
Oh, that's a great list — see, that's why we disagree on the utility of "web frameworks". My app does not use a routing component at all, and none of the existing solutions fit my use case. I also don't have an ORM and I don't think even having an ORM is a good idea (I'm currently working on moving to FoundationDB, where you can get extreme gains by coupling your app closely with the database, rather than talking to it through a thin straw).

I don't use templating, at least not for web pages.

User input validation — that's something I've spent the better part of several years working on, but in a larger context of a toolkit for dealing with forms, tables, data presentation, filtering and sorting. I daresay the solution I have now (which uses ideas dating back to Smalltalk) is way more extensive and flexible than what every "framework" out there has.

Re:Why is Jepsen written in Clojure? by theonething on Thursday December 07, 2023 @10:58PM (#38565279)
> User input validation — that's something I've spent the better part of several years working on

And that's why I use good frameworks.

Re:Why is Jepsen written in Clojure? by jwr on Friday December 08, 2023 @07:40AM (#38568301)
I don't think there is a framework out there that does what I need it to do, but I'd be happy to learn — which ones did you specifically have in mind?
Re:Why is Jepsen written in Clojure? by rafaelmn on Wednesday December 06, 2023 @07:50AM (#38543162)
Because of it's lisp nature with special braces I find it to be nicer for creating DOM than HTML :

   [:div
     [:p "I am a component!"]
     [:p.someclass
       "I have " [:strong "bold"]
       [:span {:style {:color "red"}} " and red "] "text."]]
really has that "first class" feel when you're working with it rather than feeling tacked on like JSX - at least that's how I remember it.

My main problem with Clojure was the dynamic nature of it. I have not used it in very long time now (probably 7 years at this point) - but despite the amazing aspects of it I would not trade in TypeScript annotations.

A question for clojurists here - what is the level of static type checking adoption in CLJ world ? When I was using it last time there were some things like schema validators, but nothing like TypeScript. It looks like there's static typing annotations support now but are the types widely used by popular projects/provided for big libraries ?

Re:Why is Jepsen written in Clojure? by jwr on Thursday December 07, 2023 @05:16AM (#38554832)
From the point of view of a solo developer maintaining a large app over many years: I would not want to deal with static type checking and I would not find it useful, except for simpler subsets of my code.

I do use spec, and I've used other checking solutions before. I also use :pre/:post conditions a lot, as well as plenty of assertions. But in a large and complex application the errors I'm likely to run into are not as simple as a mismatched type. My most valuable checks and specs constrain multiple data fields.

Thinking about stuff I run into, I would say that the majority of errors are due to optionality — where a key is optional in some contexts, but mandatory in others.

Re:Why is Jepsen written in Clojure? by gleenn on Wednesday December 06, 2023 @04:34AM (#38541988)
Luminus has been around a long time and Kit is newer. Most Clojurists believe in libraries over frameworks though so that's why you don't hear about web frameworks much. I've messed with Luminus a few times and it is really easy to pull out parts and swap in almost any bit of it. They document a lot well and make it really easy to pick different parts out of the gate like different DBs, JavaScript libs, and a lot more. The maintainer roams HN frequently as well :)
Re:Why is Jepsen written in Clojure? by aphyr on Wednesday December 06, 2023 @09:27AM (#38544271)
Aphyr.com is built with Luminus. :-)
Re:Why is Jepsen written in Clojure? by gengstrand on Wednesday December 06, 2023 @11:39AM (#38546197)
Whatever happened to ring or donkey?
Re:Why is Jepsen written in Clojure? by gleenn on Wednesday December 06, 2023 @11:40AM (#38546203)
Luminus uses Ring.
Re:Why is Jepsen written in Clojure? by epgui on Wednesday December 06, 2023 @06:32AM (#38542580)
I know you’re probably going to think this answer is crazy or stupid, but you don’t need a web framework in clojure. In fact you don’t need all the libraries that many languages need.
Re:Why is Jepsen written in Clojure? by olavfosse on Wednesday December 06, 2023 @05:23AM (#38542237)
Re:Why is Jepsen written in Clojure? by daveliepmann on Wednesday December 06, 2023 @06:05AM (#38542447)
It has several. None of them dominate; most people assemble their own from individual libs.
Re:Why is Jepsen written in Clojure? by yogsototh on Wednesday December 06, 2023 @12:03PM (#38546524)
Let me add my 2cents on this subject.

I feel that due to its functional nature or perhaps this is just the community bias, Clojurists tend to prefer mixing lower level libraries to build their web application instead of relying on a specific big web framework like RoR for example. Luminus would be one RoR-like system.

But today, I think people would probably choose reitit for the writing the API and use a clojurescript framework for the frontend or perhaps still use reitit to generate HTML pages using hiccup.

Re:Why is Jepsen written in Clojure? by alberth on Wednesday December 06, 2023 @08:15AM (#38543421)
What % of the overall benefits would you attribute to the JVM vs. Clojure (the language)?
Re:Why is Jepsen written in Clojure? by jwr on Thursday December 07, 2023 @05:11AM (#38554796)
I barely even care about the JVM. I'm happy because it is an impressive feat of engineering, representing tens of years of huge investment into development, compiling my code to levels of performance that poorer VMs cannot reach. But JVM is just one of the environments where my code runs (the other is the JavaScript VM in browsers).
Re:Why is Jepsen written in Clojure? by iLemming on Thursday December 07, 2023 @04:02PM (#38561780)
Clojure is not only on JVM. There's Clojurescript. There's ClojureDart. There's ClojureCLR. There a bunch of experimental things like ClojureRS (Rust) and Clojerl (for Erlang). You can "talk to" Python and R from Clojure. You can use Fennel if you need to deal with Lua (It's not Clojure, but it's very Clojure-like lang). The benefits are there, for any platform you choose.
Re:Why is Jepsen written in Clojure? by pif on Wednesday December 06, 2023 @10:23AM (#38545015)
Out of topic, sorry!

> Backwards compatibility is hugely important

Why is this always considered a Good Thing (TM), apart when applied to C and C++?

Why is it OK when languages and systems are bent backwards in order to avoid breaking stuff that works, but the two languages that together support a huge part of the running software are expected to up and break ties with their glorious past and present?

Re:Why is Jepsen written in Clojure? by yogsototh on Wednesday December 06, 2023 @12:10PM (#38546648)
Let me talk about my experience. I was (yes was) mostly an Haskeller. I loved using Haskell, and even a long time ago (in 2007 I think) when I learned it, the book to learn the basic of the language had snipped that no longer worked.

But I still loved, it. And it changed every year, and I was even part of the proponent of the changes.

But after a while, you realise that your old project stop working. That if you want to use a new library, you also need to update many dependencies. But each one has breaking changes, so you start updating your code.

Mainly, if you wrote some code, and forget about it, it will no longer work or will be very hard to use with newer libraries. After a while this became very tedious.

In Clojure, the code I wrote 10 years ago is still working perfectly today. The application still launches.

If a bug is discovered and I need to fix it, for example, by upgrading or adding a new lib, I am not afraid to loose hours finding an fixing my existing code that suddenly become deprecated.

So yes, stability is VERY important for me now.

And last but not least, Rich Hickey talked about it in this talk and make a lot of very great points:

https://piped.video/watch?v=oyLBGkS5ICk

Re:Why is Jepsen written in Clojure? by rhaen on Wednesday December 06, 2023 @11:15AM (#38545860)
I'll also note a lot of objections to the way C++ does backwards compatibility is their adherence to an ABI which they refuse to break, but also refuse to say they'll never break.

Many of the problem that can't be fixed for backward compatibility reasons are because they'd break the ABI, not new code. I think that's very different from other language's policy, which, from the ones I'm more familiar with, is about building old and new code together, rather than linking old and new code together.

It makes for a much more restrictive, but also ambiguous and not guaranteed, set of requirements on any change.

Re:Why is Jepsen written in Clojure? by aphyr on Wednesday December 06, 2023 @10:28AM (#38545093)
There's a happy medium, I think, and I also imagine that depends on scope of change and the kind of applications involved. Speaking personally, I'm OK rewriting code, say, every decade. In the Ruby world, things moved so fast that my code would rot every six months. Now that I've been maintaining the same software for 20 years I'm really starting to care about that. ;-)
Re:Why is Jepsen written in Clojure? by pif on Wednesday December 06, 2023 @10:33AM (#38545171)
> I'm OK rewriting code, say, every decade

If it is your code, or your company's code, why not? But think about dependencies!

Re:Why is Jepsen written in Clojure? by aphyr on Wednesday December 06, 2023 @10:59AM (#38545589)
I maintain dependencies for a lot of people--nowhere near operating systems or stdlibs, but my OSS gets fairly broad use--and I try very hard not to change their APIs too much! It's a real concern.
Re:Why is Jepsen written in Clojure? by wiseowise on Wednesday December 06, 2023 @03:27PM (#38549040)
First one is a security nightmare, second one probably has more features and intricacies than other top three (by popularity) programming languages combined.