Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

After using it with Datomic Cloud, do you prefer it also for local projects? Is there something that happened with Datomic Cloud configuration that made it “click” for you elsewhere? Did you just have to use it there and that experience informed your preferences?

Data > functions > macros is a core concept of Clojure. Does that come into play here?

These are prompts from a curious outsider’s perspective.



I do.

I guess it boils down to the fact that I don't find it significantly harder to use than Leiningen, there are great libraries and tools that work well with it (shadow-cljs can source its deps from deps.edn for example), and I wrap the entire thing in a task system anyway (lately, Babashka tasks).

I guess it helps that its the "official" way to do things, but that's not a primary concern for me.


Thanks. I hadn’t even considered Babashka, which I’m quite intrigued by.


I found an old thread that examines some of the early usage of deps. Data > macros does indeed seem to be a driving force: https://clojureverse.org/t/combining-tools-deps-with-leining...

tools.deps makes better choices when dependency specs conflict, so I would suggest trying https://github.com/RickMoynihan/lein-tools-deps if you otherwise want to use lein, and get the best of both worlds.

By better, I mean:

> Leiningen and Maven, when there is a conflict always pick the version that is closest to the root of the dependency tree; where as tools.deps always picks the newest.


Leinengen vs Maven dependency resolution is pretty distant to my concerns. I may be in the minority there, but I don’t think I am. I guess the thing I’m struggling to understand in the build tool differences is:

Leinengen’s (defproject) takes a series of keys and values. It is declarative. You can probably get into dependency hell if your config is complex enough, and I’m almost certain it’s doing more than I understand under the hood. (like why doesn’t it just take a map instead of being a macro?)

tools.deps OTOH appears to need both a bunch of top-level definitions in a namespace (instead of a map literal) AND a hand-rolled build.clj file with custom functions to do most of the things that leinengen considers to be boilerplate. This does imply that you have much more flexibility with tools.deps, but it also raises the bar for entry, and it doesn’t appear to be as data-centric.

If I want to do ANYTHING meaningful with Clojure, I need a project environment to start with. I am not confident about how to do this with clj, even after reading https://clojure.org/guides/deps_and_cli#_writing_a_program Maybe I just haven’t found the right guide, or maybe clj wants me to commit more to working REPL-first than my dev environment (VS Code + Calva) has good support for.

What I’m wondering now is, if the gains that tools.deps provide are worth the entry price, does it make sense to have something like “create-react-app” to generate a project directory with sane defaults that can be customized if/when needed, if your project doesn’t fit the 90% case? Does this already exist?

‘dustingetz linked the Simple Made Easy talk. I get the distinction between the two, and I don’t want to swallow the hairball. I’m already sold on the Clojure paradigm.

But I ALSO still want to “get this instantly and start running it in five seconds,” and I don’t understand why I’m not allowed that if I choose tools.deps. I don’t think the two goals are more than accidentally orthogonal.


You keep saying tools.deps but I think you mostly mean tools.build here.

For the CLI -- which uses tools.deps under the hood (not the brand new tools.build) -- all you need is your deps.edn file: a declarative hash map describing your dependencies and, under aliases, any additional tools you want to use.

The build.clj file is something some folks have already been doing in one form or another for large, complex projects (and would be familiar to anyone using Boot instead of Leiningen).

tools.build provides some common tooling and structure that should help reduce the complexity out there by providing a standard way to do a number of tasks that folks were already doing a different way (yes, including some of the core Leiningen tasks) and to provide a composable, function-based set of tools to help you write your own build scripts.

The bottom line: if Leiningen does what you need, great! Keep using it. If you find Leiningen to be restrictive and not a good fit for your project -- as we did, years ago -- then tools.build might be better. We left Leiningen for Boot many years ago and if we hadn't started to run into bugs/issues with Boot at scale we'd probably still be using it. Instead we switched to the CLI/deps.edn back in 2018 and we've just adopted tools.build which has simplified some parts of the build script we already had.


i agree that it’s possible to have both, but you have to start with simple, and as he said in the talk which we just reread, easy is often relative to your local priors

also those custom hand rolled fns are … a library, which is way better than a build plugin


Thanks. I didn’t even know that leinengen has plugins.

If tools.* is the language maintainers’ preferred method, I think there is value in having a single command to set up a “simple/default Clojure project” in a folder, even if that only cuts the commands down from four to one.

  $ mkdir hello-world
  $ cp deps.edn hello-world
  $ cd hello-world
  $ mkdir src
I don’t understand where that deps.edn comes from in a fresh project. It’d be great to have “clj create hello-world” build one for me in ./hello-world, use my running Clojure version as a dependency (if that’s how “clj” works), create the child src/ (and /test if that’s a best practice) folders, etc. The idea being to generate a local library on-demand with sane boilerplate defaults and almost no knowledge. I can learn later what Else I might need if I can get it up and running quickly first.

Leinengen looks easier to me for my admittedly trivial use cases, because I don’t need a library or plugins at all. And again, I might be in the minority. But if folks keep saying “lein handles 90% and is easier,” and if we can make tools.* handle those same 90% cases trivially, it seems worthwhile.


If you're using the latest (prerelease) version of the Clojure CLI:

    # this is a one-off step to install the clj-new tool:
    (! 646)-> clojure -Ttools install com.github.seancorfield/clj-new '{:git/tag "v1.1.324"}' :as new
    Installed new
    # now you can run it anywhere to create new app or lib projects:
    (! 647)-> clojure -Tnew app :name myname/myapp
    Generating a project called myapp based on the 'app' template.
    (! 648)-> tree myapp
    myapp
    |____.gitignore
    |____.hgignore
    |____CHANGELOG.md
    |____deps.edn
    |____doc
    | |____intro.md
    |____LICENSE
    |____pom.xml
    |____README.md
    |____resources
    | |____.keep
    |____src
    | |____myname
    | | |____myapp.clj
    |____test
    | |____myname
    | | |____myapp_test.clj
This is already set up with testing and JAR building for you:

    (! 649)-> cd myapp
    (! 650)-> clojure -X:test
    
    Running tests in #{"test"}

    Testing myname.myapp-test

    FAIL in (a-test) (myapp_test.clj:7)
    FIXME, I fail.
    expected: (= 0 1)
      actual: (not (= 0 1))
    
    Ran 1 tests containing 1 assertions.
    1 failures, 0 errors.
    (! 651)-> clojure -X:uberjar
    [main] INFO hf.depstar.pom - Synchronizing pom.xml
    Skipping paths: resources
    [main] INFO hf.depstar.aot - Compiling myname.myapp ...
    [main] INFO hf.depstar.uberjar - Building uber jar: ./myapp.jar
    [main] INFO hf.depstar.uberjar - Processing pom.xml for {net.clojars.myname/myapp {:mvn/version "0.1.0-SNAPSHOT"}}
    (! 652)-> java -jar myapp.jar 
    Hello, World!


{:paths ["src"] :deps {org.clojure/clojure {:mvn/version "1.10.0"}}}

that's it


You don't even need that -- those are the defaults for the CLI.

    (! 639)-> mkdir fresh && cd fresh
    (! 640)-> mkdir -p src/myns
    (! 641)-> echo '(ns myns.myfile) (defn foo [{:keys [name]}] (println (str "Hello, " name "!")))' > src/myns/myfile.clj
    (! 642)-> clojure -X myns.myfile/foo :name "filoeleven"
    Hello, filoeleven!
No deps.edn file needed -- until you want to add extra dependencies etc.


I haven't used Datomic at all but I do prefer the CLI and deps.edn for all my projects. I really haven't used Leiningen for years at this point -- I mostly only use it now when I'm helping a beginner debug some problem they've run into with Leiningen plugsin.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: