Hacker News new | ask | show | jobs
by AtticHacker 1799 days ago
I agree. To me tools.build is not a replacement for Lein at all. Lein is more intuitive to most beginners. It's much easier to tell someone to run `lein new some-app` and `lein run` / `lein uberjar`, than to tell them to configure their deps.edn file so they can run some alias with the `-X:...` / `-M` arg to create and run a new project (and who knows which dependency to use / configure to build an uberjar).

For experienced Clojure developers this might seem trivial, but new people (in my experience) are very impatient and want to get started ASAP. Honestly, who can blame them? Why does it have to be so difficult in this day and age?

Another thing I hear Clojure developers say is that beginners can start with Lein, but once you get more experienced with Clojure you can switch to tools.build. Why does a build tool need to be so unusable that you can only use it when you become more familiar with the language? You don't see that with Ruby's Bundler, or Elixir's Mix. They just work, just like Lein does.

2 comments

> RICH HICKEY: I think that, collectively, we are infatuated with these two notions of easy. We are just so self-involved in these two aspects; it's hurting us tremendously. Right? All we care about is, can I get this instantly and start running it in five seconds? It could be this giant hairball that you got, but all you care is, can you get it.

Simple Made Easy is what attracted me to Clojure, and tools.build, tools.deps, tools.cli are aligned with this mission. Cognitect is doing exactly what they said they would do and have been doing all along.

Re-read the talk here: https://github.com/matthiasn/talk-transcripts/blob/master/Hi...

(PS, a note to Cognitect comms – maybe start here with your next blog post and see if people react differently!)

You forget that on the ground-floor, where programming languages compete for mind-share, easy matters. In fact easy, in terms of getting something working, trumps difficult simplicity any day of the week. Easy is part of what makes an employer want to use your technology.
> In fact easy, in terms of getting something working, trumps difficult simplicity any day of the week. Easy is part of what makes an employer want to use your technology.

The whole point of the talk is that choosing "easy" (as in easy to get started) solutions while ignoring the complexity will be harder to maintain in the long run over choosing the "simple" solution that takes a bit more time to set up. Personally, this tracks pretty closely with my experience.

(Relevant slide from the talk: https://res.infoq.com/presentations/Simple-Made-Easy/en/slid...)

To get started with clj, you need 0 files. From a project directory, you can just type `clj` and get a REPL that includes Clojure and source files in src/. You can add new source files and immediately invoke them with `clj -X`. You can push that project to github and others can immediately use it from another project using a github url/sha. This is far "easier" than leiningen for getting started. The comparative experience there requires creating a project.clj with a bunch of keys, building a jar, getting an account and keys on clojars to deploy it, etc.

There's lots of other things you can do with clj - these are all additive. At some point, you might (possibly) need a build script. When you do, it's written in Clojure using a pretty straightforward set of functions and you can copy/paste in a starting point. You can grow that build file forever.

Bit bold to assume that the people making these decisions "forgot" anything. Design's about trade-offs.

The claim here is that the thing that makes your language easier to pick up initially nonetheless hobbles it for long-term use - refactoring, adding features. There is a business case for making the latter easy at the expense of the former.

Code can be easy or hard to write and/or change at various levels of complexity, and it's hard to solve for everything when designing a language.

that is completely true and maybe even clojure’s achilles’ heel, but you can’t come here and say they didn’t tell you
Rich can try to redefine the English language all he wants, but he'll find it a lot more difficult than redefining Clojure.

The fact is, the solutions the core team have been putting out for the last several years have been neither simple or easy, and in fact tend towards a weird and arcane complexity in service of problems no one seemed to have.

I remain baffled by Spec, by the clj tool, by deps, and now this. At every step it seems as if the team lives in their own world, and not in ours, and each new tool is as cryptic and convoluted as the last.

They frequently don't even seem to encourage code that is consistently idiomatic to how the rest of us even write Clojure. Who else was even using namespaced keywords for anything until Spec decided to not only use them, but link the entire mechanism to a mutable namespace registry? How is that "functional" in any way?

> and tools.build, tools.deps, tools.cli are aligned with this mission.

No, they are neither simple nor easy. They make new project setup un-necessarily hard, they make builds un-necessarily hard and complicate stuff for both newbies and intermediate programmers. Only experts with tools.* may be comfortable with this and I have seen these experts actually copy sample template `deps.edn` for new projects and use long complicated aliases.

For both simplicity and ease-of-use this should be done by a tool and not a human.

When I recommended some friends to Clojure, they stopped after getting stuck in deps.edn. Clojure setup feels more complicated than C++/Java/Kotlin/Python project setup nowadays.

I wish Clojure would use Rust's Cargo for inspiration.

`cargo new --bin projName` and open the folder in your editor/IDE of your choice.

We migrated from Leiningen to Boot and then to the CLI/deps.edn. Leiningen was too rigid and too much ceremony to write new tasks for. Boot was great from the "writing new tasks" point of view but the fileset abstraction and the pod pooling were both pain points for us. We've been very happy with the CLI and deps.edn and we're already using tools.build at work to streamline our (Clojure) build script.

We have a fairly large codebase (113K lines) in a monorepo with over a dozen artifacts built from about fifty subprojects. Leiningen really wasn't a good fit for us so we're very glad of alternatives.

Thank you for the perspective (and also for clj-new — it feels like it should be built into Clojure’s own tooling).
Now that tools.build is here, I think clj-new can be substantially simplified (copy-dir with text replacement is most of what clj-new does for built-in templates) and when add-libs gets to the main branch of t.d.a or Clojure itself, that takes care of a lot of the rest of what clj-new does.