What do beginners struggle with?

We’ll probably never be able to get this easy, since I doubt OSX will bundle Clojure with the OS anytime soon, the way it does Python, but I think things will get easier, and I can tell you already have compared to just a few years ago.

Oh, zero setup is kinda hard to do without OS support :slight_smile:

AFAIK you can skip homebrew if you don’t already have it. You can download a JDK from https://adoptopenjdk.net/ and then install Clojure from the Linux script (I think).

If you have homebrew, I don’t think you need to set any environment variables or paths - things should just work.

I think https://github.com/borkdude/babashka is great for newcomers. Coming from Python and discovering Clojure in 2016, I wanted to explore its syntax just by hacking in a .clj file like I did in my .py files, but that was not meant to be. In 2020, Babashka delivers on this. It is easy to install and has great error messages.

2 Likes

The links provided and explanations were great. I managed to get a REPL set up, following step by step the instructions in the links:

Homebrew set up was a bit long as it seems to involve a Xcode upgrade.
Java install via Oracle went very well.
CLJ install went well with clear instruction for extra mappings (if I remember well).
Set up of Lien was easy as they provided a link to a Homebrew process.

Overall, thanks to your support, I have a working REPL (Lein REPL to be precise). You help me beat my expectations ! And I’ve so much to learn about Clojure now…

4 Likes

Feel free to drop by #begginers in Clojurians slack that is meant to help with, uh, beginners:)

1 Like

What I personally struggle as a beginner is finding small open-source projects which I read and learn from.

I also had some problems with this. When I had problems finding examples for a library in use, I would search GitHub for the lein/deps.edn signature, which usually yields something.

1 Like

I am just beginning to learn Clojure. I feel there is an abundance of good tutorials out there about the language itself, about syntax, semantics, small code snippets and so on.

I am actually struggling much more with setting up a toolchain and the integration thereof. Do I need Maven? What are Leiningen or CLI actually doing? Do I need them or not?
Where can I find packages and what is the best way of integrating packages? Git? What do I need for the editor? Pareditl? Calva? What are Uberjars and when do I need them? Etc etc…

Which tools do i really need, how do the tools interact and depend on each other and how I integrate all the tools into my IDE? (I my case: Leiningen and VSCode with Calva)

What I am really missing is a guide or tutorial on the toolchain (When anyone know one, I haven’t found any?). Currently I feel I spend 90% of my learning time trying to find out about the tools and just 10% time actually on learning Clojure which is pretty frustrating.

1 Like

Lots of questions! Here are some quick answers to most of them, to get you started:

Do I need Maven?

No.

What are Leiningen or CLI actually doing?

Leiningen can provide a REPL, run code, run tests, manage dependencies, create new projects, package code – and has a whole host of plugins available.

The Clojure CLI is a newer, official piece of tooling from the Clojure/core that focuses on building a classpath (managing dependencies), and providing a REPL or running code. It has community tooling (Tools · clojure/tools.deps.alpha Wiki · GitHub) that can run tests, create new projects, package code and so on.

Do I need them or not?

You need lein or clojure / clj or boot to run a REPL, run code, etc. Most of the books and tutorials out there still focus on Leiningen because it’s been around “forever” but we’re starting to see more books and tutorials featuring the Clojure CLI now. Boot has always been a much more niche tool, but some people love it, for its programmable nature.

As an aside, at work we started with Leiningen back in 2011 because it was the only option. We switched to Boot in 2015 when we needed more flexibility, as our codebase grew. We switched to the Clojure CLI in 2018, after starting to run into quirks and bugs with Boot, as our codebase grew larger. We now manage 100,000+ lines of code in a monorepo with 30-ish subprojects, all with the Clojure CLI and a simple bash wrapper (mostly to allow us to run multiple clojure commands from a single invocation).

Where can I find packages and what is the best way of integrating packages? Git?

In general, Clojure packages are deployed to clojars.org and most projects have a README that explains how to provide the “coordinates” for Leiningen (and the Clojure CLI) to find the package. lein has a project.clj file containing a :dependencies vector that lists coordinates of libraries you want to use in a given project. The CLI has a deps.edn file containing a :deps hash map that lists coordinates of libraries you want to use in a given project. You may find https://www.clojure-toolbox.com/ helpful for discovering libraries that may be useful to you.

Note: in Clojure, it is common for libraries to be small and focused on solving just one problem. Therefore, they are often “complete” and in need of very little maintenance, even if their version number hasn’t reached 1.0 yet (and often extremely stable even if they are marked “alpha”). That’s very different from most other language ecosystems.

If you are using the Clojure CLI, you can easily specify project coordinates with a :git/url and a :sha to depend on a specific version of the code from GitHub – but the project has to also be a deps.edn-based project.

What do I need for the editor? Pareditl? Calva?

It sounds like you’re using VS Code? I’ll leave that up to others to answer but Calva is definitely the most up to date for VS Code. I use Atom (with Chlorine, lisp-paredit, and parinfer). The choice of editor is up to you – it’s often easier to continue using whatever you’re currently using, as long as it has Clojure REPL integration.

What are Uberjars and when do I need them? Etc etc…

An “uberjar” is a package of your app, Clojure itself, and all the libraries your app uses. It can be run with just a java -jar command so it is a good choice for production deployment, to environments that just have a JVM in place. Leiningen has both jar (library) and uberjar (application) building tasks built in. The Clojure CLI requires one of the tools listed on the wiki I mentioned above. I use depstar (because I maintain it and use it heavily at work).

10 Likes

I can appreciate the time you spend on answering the questions. But I wasn’t so much for looking for answers for these specific questions, they were exemplaric for the tons of questions you have as a beginner.

Quite a lot of the tutorials out there on different Clojure related topics assume that you have all tools up and running and know exactly how to use them

This is quite understandable because the authors of these tutorials using their tools for along time, and it is not subject of their tutorial to explain the tools. But as a beginner, you sometimes do not even get the example code on top of page 1 running because your toolchain is not set up, and after 2 hours research you somehow find you shold have put this or that in your project.clj or deps.edn file, or used Leiningen to setup your project for the examples.

The point I wanted to make is that a comprehensive introduction into the tooling is missing and how the tools depend and interact with each other. You can find bits and pieces about every single tool, but it’s really an uphill fight to bind everything together, or more specifically it’s more of a barrier to entry than the language itself.

1 Like

I admit that I don’t know of a lot of material covering tools. I just wanted to bring up, I’ve found for me, the order was learn language, try tools, learn the language for real, realize all tooling is just core language features wrapped in pretty interfaces, which made understanding the tools afterwards much easier.

2 Likes

100% agreed. The main obstacles I see are:

  • lack of funding, like so many projects; this could be solved by Clojurists Together
  • inter- and intra-tool churn (e.g. the rise of Atom and breaking changes in CIDER, respectively)
  • people have different preferences, causing fragmentation (I prefer emacs-style keybindings, whereas many of my colleagues prefer vim-style; this makes writing instructions/docs/manuals cumbersome and the end result is that each person’s combination of tools is unique to them)

As a newcomer to Clojure remembering the data’s shape is my hardest problem too. I do secretly wish for types and a way to give a typedef to a data shape and it it in the signature of functions.

2 Likes

Why not use spec?

may i ask how things went for you?

'for` as loop.

I made

(defn print-numbers []
  (doall (for [n (range 1 27)]
           (do (println n)
               (Thread/sleep 50)))))

instead of

(defn print-numbers []
  (loop [n 1]
    (when (<= n 26)
      (println n)
      (Thread/sleep 50)
      (recur (inc n)))))```

You might also find doseq useful. It’s like for but for side effects, such as printing to the standard output.

2 Likes

I agree with both of them, who mentioned that knowing the shape of things is a problem. I considered spec and thought that it would help, but as a beginner I’m yet learning another thing that I don’t know how to fit with the rest, particularly in a project. I saw Rich saying in a talk that working with map would have different phases, from confusing to enabling (there were more steps), so I’m trusting him.

I feel like this shape thing will be less of a problem once I’m able to fully leverage the REPL workflow. Is that something you folks would agree? Getting there hasn’t been straight forward, but knowing this would be motivating. Also @seancorfield’s tutorials will probably help (I can update you next week).

Thanks folks!

1 Like

Yes, if you can get a really good REPL-based workflow going, it will be a major help! Never type into a REPL, always eval code from a file, use comment forms for “scratch” / exploratory code to eval things that you don’t want to be part of your source/test code (yet). Evaluate everything as you write it and as you change it. Then you get used to exploring the shape of everything you’re working with – all data becomes tangible in the REPL.

3 Likes

It is, and getting fluent with the REPL will help. However, it’s a good idea to document what goes into those maps (it’s not an issue when writing code, but it may be when reading code you wrote months ago). If spec is overkill, you can sometimes achieve a good compromise e.g., by using destructuring in your fn arguments, so you at least have an idea of what you should expect to find in those maps.

2 Likes