What do beginners struggle with?

Thanks! This is great stuff for us who want to help beginners struggle less. I do hope you will persist in checking Clojure out despite the lack of material for the total beginner.

I especially recognise the confusion around the REPL and various REPLs-this and that-REPLs. And, yes, it is a bit unfortunate that so many tutorials guide you to a REPL prompt that you are later not supposed to use. This is why Calva’s Getting Started REPL guides you to an editor/file connected REPL. (As you are a Windows user, I should probably tell you that it will not work if your Java is installed with Oracle’s installer. They have a bug there before JDK17.)

3 Likes

Thank you for the suggestions and the encouragement, Michael and PEZ. I shall check them out.

But it does speak to my initial point that Clojure might be good for beginners, but it is by no means beginner friendly: lots of tools and tidbits I can download and figure out, yet nothing actually helps me learn how to code in this language (or figure out what I’m doing wrong when I try applying what I’ve learned).

Beginner resources are… hard. I don’t feel like plotting shapes with a pretend turtle (been there, back in the day when Logo was an actual language), but that means I’m stuck at being a little teapot, because what seems to be the most beginner friendly book out there assumes a noob can go from
loop [iter 0]… recur (inc iter) ; easy enough
to
loop [vector] [some other vector] [yet another vector]… recur ([vector which has nothing to do with anything in the loop point] (set stuff into other stuff and call everything “parts”)
like it makes perfect sense.

Trying to write anything on my own is equally jarring. Clojure says I see your effort, and I raise you a stack trace, a mile long, which you won’t understand. Sucker!

The whole business reminds me a bit of the stories I’ve read about installing Arch. “If you can’t figure it out on your own, you should probably be on Mint.”

Sorry, I sound whiney. Not my intention. Since beginner struggles is the topic, and I’m a beginner, maybe what I say will help the cool Clojure kids make the language, and experience, more accessible to future beginners.

(Btw, thanks for being positive and helpful. This is my first interaction with the community, you lot are making it a good one.)

1 Like

Since Clojure is a hosted language – both on the JVM and on a JS engine (browser or Node.js) – it’s never going to be easy on its own for a complete programming beginner, unfortunately, because you will have to learn enough of the host ecosystem to be able to figure out how to navigate that boundary, even where Clojure tries to hide it fairly well. And you’re right, all of the Clojure tutorials seem to assume some level of knowledge of at least one other programming ecosystem :frowning:

There are a few editor setups that do a good enough job at hiding the underlying machinery that you can make progress without having to learn about Clojure installation and REPLs – but even they still assume you have managed to get a JDK installed (and, as @PEZ notes above, even that can be fraught journey with some versions on some platforms). And there’s nothing whatsoever about getting “an appropriate” JDK installed that is beginner-friendly :frowning:

There’s also the issue of operating systems. Despite all the progress made over the years, Windows is still very much a 3rd-class citizen in the Clojure world: 53% of Clojurians use macOS, 37% use some flavor of Linux. Of the remaining 10% on Windows, it’s split half-and-half between folks using WSL2 (i.e., hosted Linux) and folks using Powershell. Working with VS Code and Clojure is much, much nicer on “Windows with WSL2”, in my experience, and again most of the tutorials out there assume macOS or Linux not Windows – but getting a good development workflow set up on Windows/WSL2 is not something for a complete programming beginner :frowning:

And as noted here (and in the Hobby Programmer thread), the initial learning experience with Clojure is nearly always couched in terms of typing into the REPL, which only gets you so far. To really work with Clojure in any productive way, you need to have an editor setup with a fully-integrated REPL (that you never type into!) so that you can evaluate code from your editor with just a hotkey and develop your app “live” as you type code into your source files. And for debugging etc you often need (or at least some people want) additional dev-specific libraries and tools. It’s a huge hill to climb from just “typing into the REPL” and, again, a mountain for a complete programming beginner :frowning:

7 Likes

Just a random thought:

What if we had a downloadable virtual machine (like a VirtualBox VDI) that contains everything a new person to Clojure would need? For example, preinstalled and configured VS Code with Calva, Emacs with Cider, example projects, empty starting project, etc.

The advantage of this is that it would ensure we have a common starting point for anyone that wants to try out Clojure, with a environment that is set up in a way to encourage good development practices (like using the REPL in the right way).

The main problems I can see is that: (1) it will require Windows users to use a Linux distribution, (2) big download, probably several GBs, (3) require new users to install VirtualBox.

The easiest way to get this set up would probably be to use something like https://www.vagrantup.com/ to set up an environment with everything needed to get started with Clojure development.

If you are a beginner, is this something that you would be interested in?

5 Likes

When I was frustrated with Clojure I did a bit Python and lots of Javascript. I learned a lot there too. The good thing with Clojure is that everything is pretty stable and the build tooling is much better. When you are stuck you can pause a project and resume working on it months later when you learned enough to start again. Projects usually will still work unless for example in Javascript land where deps break too often to make working on long time projects enjoyable.

2 Likes

I guess OpenJDK 16 and Calva play nicely together on Windows, because I just got the thing up and running! Thank you for the suggestion, PEZ

And @seancorfield I must say, I think I am starting to see the appeal of not typing in the REPL! Typing everything in the REPL wastes a bunch of time, for one.

Alright, back to the grind. Thank you for the help and motivation, everyone.

5 Likes

Great to hear you are up and running. It is very unfortunate with that JDK bug, but at least we now know about it.

Yes! I think trying to get it down to zero-installs is the way to go. There actually is a ”virtual” machine like this: Gitpod. I’ve updated my Rich 4Clojure project to work there and also updated its README to try to make it more accessible to beginners.

It would be super nice to get some feedback about how this might work out for a beginner. Can you give it a spin @jaco ? And all of you, of course.

1 Like

Busy working through the 3 help files now. Looks awesome. So far, it helps that I don’t have to install anything.

1 Like

Hi folks,

I read this thread with interest, especially the replies by @HolyJak @PEZ and @seancorfield. As a complete #Clojurenoob, this thread really resonated.

But as I read the thread, I realise that there are beginners, and there are beginners. Some of the beginners here make me feel that they are misnamed: they might be beginners in Clojure but they definitely feel very experienced as developers!
And it dawned on me that, maybe it makes sense for us to clarify further what we mean by beginners.

I will speak first for myself: I am a beginner-beginner, in that I completed an online web dev bootcamp, so I know basic HTML, CSS and Javascript, but haven’t really practiced those because I have an instinctive feeling that I will develop a lot of bad habits… so I basically followed the web tutorials, and can do some very basic commands. But I really disliked the messiness of JS, which feels very unclean and untidy mentally: very hard to debug… I only started last year, so am really a complete noob not just in Clojure, but to the world of programming in general.

Besides me, there are people who have a couple of years’ experience in other languages. They are then exploring Clojure. I think they are the next segment.

Then there are beginners to Clojure, but who are highly experienced in other languages, some with 10+ years’ experience. I suspect their needs will differ from the above two categories.

So when we talk about beginners, it really spans a spectrum, each with different needs.

I suppose the corollary question in my head is, is there a segment of beginners that y’all want to focus on first?
Related to that question, is the question of which segment of beginners should y’all focus on first? (I don’t have answers to the questions I am raising btw)

I also recently read this (great) book on open source software and how it has changed a lot thanks to Github and the rise of Javascript: the book is called Working in Public. In there, the book talked about how the nature of OSS has changed a lot, and how the rise of JS has also meant that many maintainers struggle with dealing with HUGE numbers of low-quality pull requests.

What I thought interesting was the characterisation of the different types of communities:

  • Federations (high user growth, high contributor growth) → Rust, nodeJS, Linux
  • Clubs (low user growth, high contributor growth) → AstroPy, but also Clojure, Haskell, Erlang
  • Stadiums (high user growth ,low contributor growth) → Babel, webpack
  • Toys (low user growth, low contributor growth) → ssh-chat

I suppose the corollary question is what segment or direction the Clojure community wants to go, and what type of beginner growth aligns with that?"

Again, I’ve no answers, just posing the questions off the top of my head. My instinct, though, is that we probably don’t want to end up being a stadium-type community…


For me as a beginner-beginner, the hard parts are learning all the basics:

  • tooling (especially finding a suitable editor, which was much harder than expected, and then setting up a REPL. I have found the IntelliJ + Cursive so far to be the easiest and most straightforward for me: initially I found Atom + Chlorine, but sadly it does seem that Atom is dying…)
  • error messaging is super opaque: they sometimes read like exclamations from Marvin the Martian to me
  • I initially also lost a bit of time wondering if I should start with Clojurescript instead of Clojure, since I know some JS. However, it’s actually a lot easier to get the tooling setup and done for Clojure than Clojurescript, so I’m taking the one-fire-at-a-time approach, and focusing on learning the language first and foremost.
  • the lack of a structured pathway with examples that I can follow. For me, I found some of Eric Normand’s videos to be super good, but they also strike me as being a bit too deep into computer science concepts for some people (I love them btw). Concurrently, I am also working through The Clojure Workshop, which is actually a REALLY great way for me to learn (as I learn best from seeing how someone does something and trying to replicate it).
  • I think what will soon follow is trying to really understand HTTP (underlying Ring), Clojurescript, etc.

But can I just say that, while the learning is tough, it is also super rewarding and I really appreciate just how friendly and helpful everyone is, on the Clojurians Slack and also on this forum? It’s amazing to see the degree of generosity and general kindness. :slight_smile: I really appreciate that, and only wish my Clojure skills were better so I can give back and pay it forward.

Peace out.

7 Likes

Hello! And thanks for this elaboration. There are so many great observations and I will certainly bookmark and consult it while working with these things. You are totally right about that there are different meanings of ”beginner”, and you provide great tools for thinking about it.

Towards the question about where the focus can be: I can only speak for myself, of course. To me it is ”all of them”. While I certainly see that we need to cover different bases for different journeys, my driver is:

You want to pick up Clojure and you struggle?

I think it is super important for us as a community to try to figure out what kind of journeys there are, and then for each one of us, as individuals, to pick a thing or two to run with.

That said, it is really intriguing to think about what we can do to make Clojure a delightful choice for learning to code.

As for your own hesitation about picking up bad habits. I don’t think you should worry too much about that. It’s inevitable, and it will happen at every stage, and never stop happening. The remedy is to keep doing stuff and get feedback and adjust. Without feedback we are all quite blind.

5 Likes

Thanks @PEZ!

That’s a really generous starting point, and I really appreciate it. :slight_smile: Thank you!

I think I can really comment on this only after I have more experience. But just off the top of my head, I think the biggest differences I’ve encountered so far are really symptoms of the different way of seeing. Like immutable data. Or the lack of for-loops (or “this”). Or the norm of “asking the REPL” if you have any question if a function could work, resulting in the very rapid, bottoms-up, iterative approach of RDD. It is really very different from anything else I’ve seen out there.

And I wonder what will happen if we have programmers who start their programming journey/career with that way-of-seeing instead of the current norm.

To clarify, I meant picking up bad habits from the web bootcamps (e.g. using “this”, or using global variables in JS). I also found myself quite uncomfortable when I learnt those, because while they got the stuff done, it just felt like… a trap? I don’t quite know why, but it just felt mentally untidy.

1 Like

As someone who’s first general-purpose learned for real was Clojure (I started learning Python, didn’t click with me so I dropped it, then learned R for work and loved it) I still struggle with Java interop, because I have absolutely no clue about Java. The rest of the language made total sense because I was already doing FP without knowing it. Mutability, classes, types are the things I find weird and hard to grasp “what problem would I fix with that”. But I’m aware this is not the majority of people.

5 Likes

Crossposting:

3 Likes
  • core.logic should be archived: it’s a rabbit hole, nobody uses it in production, the only introductory book is written in Scheme, and the documentation looks abandoned. You’ll get a better price when you sell 10 intact coffee cups than when you sell 10 intact coffee cups plus 2 broken coffee cups.
    Datalog, in contrast, was a revelation.

  • laziness is a disappointment. It promises performance gains, but those are so meager that they don’t make up for dealing with he unexpected behaviour of your code

  • homiconicity and lists: lists are rarely used in Clojure. I don’t understand why the language keeps them. Clojure forms are data, in particular: lists. If a data structure is representative of Clojure then its vectors or maps. Should Clojure be rewritten one day, then it would be better to use vectors for forms.

  • core.async is tough and there are too few books or articles that go into depth. Also, newcomers are sent to documentatiin written for golang.

  • Explanations often reference the hosting language, e.g. protocols. I don’t want to learn Java in order to learn Clojure.

2 Likes

My team uses it in production :yum:

There are about 20% of the time where performance would be a blocker to not having them, so they made sense at the time. Transducers managed to solve that problem similarly elegantly now, but they were not imagined early enough in the design of the language. Now I’d say lazy-seq are still nice for certain things, but it’s true that a lot of people feel it be nice if transducers was the default more convenient syntax, and lazy-seq the thing you reached for in special cases.

You eventually outgrow their “unexpected behaviour of your code” and stop really having to deal with that, if that’s any consolation.

I also love them for the cool factor.:sunglasses:

Fair point, I think that’s true of a lot of things in Clojure.

You mean people explain Protocols by reference.to Java interfaces?

That’s also a fair point, I think a lot of people doing Clojure have Java expertise as well, which must bias them in how they explain things.

That said, I would say that it’s important to learn the runtime memory and computation model of Clojure to become an expert in it. I think it’s important to learn that of any language. And in the case of Clojure that is the JVM. So learning about the JVM and some of its tools like VisualVM is pretty useful and it makes sense to be a part of learning Clojure. That doesn’t mean you need to learn about the Java language though.

I’ve shared that sentiment but now I’m starting to question it. After having gotten used to transducers and realizing how neatly they can be integrated into existing code, they don’t seem as esoteric and such a long reach anymore.

The question is: If you could have a language that could act as both a scripting language and a high performance language, would you prefer its default mode be scripting or high performance? If you prefer high performance, is that worth losing general laziness too?

When gluing together different systems, would you rather have a flexible language that can easily talk about endless things, or a high performance system that can only talk about finite things (with a lazy escape hatch)?

I think I’d rather the default case be the more scriptable one, for easily gluing systems together, with the option use more performant capabilities when necessary in the core performance critical areas.

And is the alternative really possible? When dealing with unbounded sequences, would it really be as easy as ‘reaching for lazy-seq in special cases’ or would it be more complicated than that, involving an entire extra streams API bolted on to the side of the language?

It would be interesting to see what the default performance of a transducers-all-the-way-down Clojure/lisp/lang would look like. Maybe that would prove useful for some things. But I think laziness is actually a better on-ramp for beginners / new Clojure developers that are gluing streaming systems together - just a little longer of an on-ramp in the beginning, to learn about forcing consumption when necessary. And then you can move gradually away from lazy scripting semantics for hot code paths in a more à la carte manner.

3 Likes

Good points, I think between lazy sequences and transducers there are things that transducers make more convoluted as well, and there isn’t a transducer for every lazy-seq function, and I think part of that is because they aren’t always all trivial to implement as a transducer, and sometimes they don’t all compose as easily together or you need to be aware of the transducing context.

I guess the question would be more what it would look like against a hybrid of eager sequence functions and transducers. For the cases of modeling infinity and such it is still a good point as too what that would look like, I don’t know if it would be better, but its an interesting thought.

Another thing, which I’ve seen sometimes as a criticism in Clojure, is that sequence functions were in the core namespace to begin with. If they had been in say a sequence namespace, you could have had another namespace named transducer or something like that. So you could have both with similar interfaces. I can’t remember why Clojire didn’t do that and choose to overload arity for transducers, when it did do it for reducers.

Anyways, to beginners reading, remember all things have trade offs and pros/cons, and I think lazy sequences over iterator style streams like Java and C#, over eager functions over transducers don’t necessarily have a clear winner, just different qualities that sometimes make one better than another. Like John said, lazy sequences do end up being a really nice default with a good balance between performance, flexibility and convenience, and there is an easy path towards performant and eager variants.

1 Like

That’s interesting! If you had to do it again, would you use core.logic, one of the rule-based libraries, or one of the datomic clones (datascript, datalevin, datahike, …)?

Thanks @didibus and @John_Newman !

1 Like

I’ll have a look at that!