What do beginners struggle with?

Oh ya, you make a great point about the doc for spit. There’s a few places like that where it is known that the doc is insufficient, or can be pretty compact and concise. I added a note to clojuredocs.org that specifies the valid options for spit. I think clojuredocs.org is the best place to find “additional” doc. It’s not only examples, if you scroll past the examples, there are notes, where people can provide additional doc or tips.

Someone probably should sign the CA, make a patch to improve the doc, and all that, but most people don’t have time for that, so they either do nothing, or they add some examples or notes to clojuredocs.org instead.

2 Likes

Thanks didibus! That’s all really clear and helpful.

Regarding the IO, I actually meant the whole thing: buffered/unbuffered, seeking, appending, streams, pipes, reading a single character from STDIN etc.

Joy of Closure appears to have one single call to (spit “file_name” something). And not a single slurp (?!)

That’s not a criticism. I’m just surprised. (I’m used to C and Perl. And no Java …)

Hum…, ya I guess I don’t know of any resource that goes in depth in all that.

I’d say the IO section in the Cheatsheet probably has the most coverage of all that. Also, this chapter is pretty good: 4. Local I/O - Clojure Cookbook [Book]

I guess, what you have to know is that everything is an InputStream or an OutputStream, which is a binary stream of bits. And then you have Writers and Readers, which operate over an InputStream or an OutputStream and do decoding/encoding of the bits for you in various ways depending on which one you use.

But ya, beyond that, IO in Clojure is really Java’s IO mechanism. So it can even help to search about that. And most IO doesn’t have Clojure functions for it either, but it is expected you just use interop for it.

You can find some docs on it here:

https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html
https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html
https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html
https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html

So for example, *in* is the process input stream, its already made into a Reader, and to read the next char you can do:

(char (.read *in*))

You need to cast to char, since .read returns an int.

There’s various type of readers/writers and streams, some buffered, some unbuffered.

I’m not sure what seeking is. Appending is done with the option of spit. And for piping, you’d read from in and output to out, for example:

#!/usr/local/bin/clojure

(->> (read-line)
     (take-while #(not= \s %))
     print)

That is thus a program that takes all input till \s and passes it to the next program:

% echo 123s456 | ./foo.clj | grep 2
(1 2 3)
   -
1 Like

Seeking is moving to a position in the file; say you want to read byte number 300 in the file, in C you’d use fseek (3) to position a cursor into the file, and then read or write from there.

In Java-land, that functionality is provided by RandomAccessFile, so you should use that.

This SO thread has an idiomatic example.

These are overly generous detailed and helpful answers :slight_smile: Much appreciated!

now… the overall theme of this entire topic is “what do beginners strugge with” and i have already pointed out the shortcomings of the clj-doc-approach in a previous post.

having said that, i think a more fundamental difficulty for beginners arises as a consequence of clojure’s quintessence, namely, being a HOSTED LISP.

what do i mean? well, first of all, it is always easier to learn / master something new, if you are already familiar with something akin to it. for example, if you do already speak
italian venturing into spanish will be much much easier for you than tackling japanese.

why? well because much of what you find in the spanish language is somewhat similar to what you already care and know about.

with japanese on the other hand everything!!! would be alien to you! instead of left-right-top-bottom people often write top-bottom-right-left, in addition to roman characters you get hiragana, katakana and last and most challenging chinese characters, instead of “normal” word order alla -bob likes lisp- you get -bob lisp likes-, no real grammatical number / gender…, counting… lets face it… counting is just a bloody mess, honorifics etc. etc.

…so… ultimately it really does come down to a different way of thinking… very much
how imperative programming and functional programming is much more about different ways of thinking, rather than any specific programming language.

so:

What’s in a name? That which we call a rose
By any other name would smell as sweet;

-----> no! global state and mutation reeks!? :slight_smile:

anyway…point is… learning about any lisp will be a major challenge, because of the unfamiliar syntax and programming concepts.

but it gets even worse! not only is clojure a lisp but a lisp hosted on the jvm!

the difficulty here is that, whenever something is hosted on something else… or providing an abstraction over something else, i am convinced that this really requires you to know about the host also… the abstraction alone does really not suffice!

for example, i have always found that the biggest problem with ORM is that people are using it without a proper understanding of the basic underlying RDB concepts.

so what i am saying is this: if you wanna learn about clojure you’d probably do well to learn some other lisp and java beforehand. ( same goes for js and cljs )

now if you look at my youtube channel you will find a programming tutorial consisting of 200 ( or so ) episodes discussing first emacs lisp, then urging the viewer to check out
some java ( “effective java” etc. ) on her own… and ONLY THEN… ( having established those crucial foundations ) do i start discussing some basic clojure.

bottom line, getting to grips with clojure is super tough, but perhaps that’s also what’s making it fun… kinda :slight_smile:

anyway… i am still struggling with clj myself,… but far from giving up!!! :slight_smile: in fact i got myself a sweet deal on the living clojure book… which has been recommended by seancorfield,… should arrive any day now :slight_smile:

final remark and coming back to spoken languages,… obviously… - really this goes without saying -… obviously one can never fully / really master any language… native speaker / programmer or not… what with the infinite and ever evolving universe of subtleties, connotations, dialects, idiolects, idioms etc. etc.

p.s. not everything in life needs to / should gravitate around efficiency, pragmatism, practicality and ( sadly looming all too large all too often ) expediency!!!

We’re losing about one language a week, and by some estimates, half of the world’s languages will be gone in the next hundred years.

Ah okay. The link to Clojure cookbook covers that then 4. Local I/O - Clojure Cookbook [Book] as well as memory mapped files.

It’s week 2 of my clojure journey, so I fall flat-faced into the ‘beginner’ category. I have no prior experience with LISPS, but have done some work on the JVM (Java & a bit of kotlin), and am marginally exposed to functional concepts (albeit via javascript).

So far the actual Clojure coding I’ve done has been limited to exercises (4clojure, koans, exercism) and replicating bits and pieces from books (Living Clojure; Clojure for the Brave & True).

The only real language-level frustration I’ve had so far is just the generic fact of not knowing enough, particularly about the stdlib, to get any momentum. But constantly having to stop to look things up is a given learning any new language or platform.

I think the ‘problem’ of lispy syntax is way overblown, at least for experienced programmers. Once you’ve been coding for a few years, you’re mostly thinking in something nearer to AST’s than the surface-level syntax anyway, and it seems like a non-issue to me to move to a different syntactical structure.

So my main actual frustrations so far have been:

  • re-arranging nested forms when I’ve got into a mess with one. This is totally self-inflicted. I ignored (good) advice not to start with paredit, and have more than once spent 10 minutes or so just trying to re-arrange something I’ve just stuffed up.
  • not knowing what tools to use, eg. lein with project.clj vs clj with deps.edn. Options with the basics are not useful to a beginner
  • not really understanding the relationship between the REPL and the code I’ve connected to it (in Emacs/Cider). Several times I’ve had errors I couldn’t fix, only to find the ‘same’ code worked in my next session. I assume I must have evaluated different groups of forms without quite following the implications
  • compiler errors are often obtuse and hard for me to make use of. They’d be impossible if I had zero Java/JVM experience
  • official Clojure API documentation tends to be terse and assumes a high level of familiarity with Clojure terminology (this is how it seems to a beginner, anyway).

I notice I’m not listing much there about the language itself, which actually seems rather clear, at least at the toy/puzzle level I’ve been inhabiting so far.

I’ve a feeling I’m going to hit a wall when I get to building real applications, lacking mental templates for the best way to arrange a bunch of functions so they don’t just form higher-level spaghetti architecture. I’ve asked around in a couple of places for excellent codebases (particularly whole apps) to use as exemplars, but haven’t come up with much. I’m wondering if there just might not be many high quality Clojure open source apps around. Still looking though.

2 Likes

I’ve a feeling I’m going to hit a wall when I get to building real applications, lacking mental templates for the best way to arrange a bunch of functions so they don’t just form higher-level spaghetti architecture. I’ve asked around in a couple of places for excellent codebases (particularly whole apps) to use as exemplars, but haven’t come up with much. I’m wondering if there just might not be many high quality Clojure open source apps around. Still looking though.

mtgred/netrunner is a good example of what a mature app looks like, although it is huge and probably pretty hard to get into. seancorfield/usermanager-example seems to have the organization of a large project, but broken down into a manageable size for learning. These are both web apps, but it’s a pretty common pattern to have separate layers for storage/DB, presentation, and routing/startup.

3 Likes

Thanks for those suggestions @John_Shaffer - added to my (fast-growing) list of Clojure resources to go through.

Completely correct on the first point. I’m a beginner and I’ve no clue how to set up a proper basic clojure REPL environment. In Python, it takes one second to open the REPL. And my python REPL stays open for days until it crashes. I read LISP REPL can run forever but setting them up is a mystery :wink:

Hi, setting up a simple Clojure REPL is the challenge for me.

My Python REPL is up and running for days in the background. Super simple to setup (no setup) and easy to use.

Have you had a look at https://clojure.org/guides/repl/introduction ? It’s relatively recent and quite comprehensive.

For the most part, folks just run lein repl (or clj if they’re using the new CLI/deps.edn but see the caveat below).

If you let Leiningen start a REPL, you can type into it – just like the Python “REPL” – and you can connect all Clojure-aware editors to it (lein repl tells you the port number its “nREPL Server” is running on and you can use localhost and that port number when connecting your editor to it. At that point, you can eval from your editor into the same REPL that you can also type directly into.

Caveat for CLI/deps.edn: unlike lein repl, this just starts a simple interactive REPL that you can type into. There are various ways to start other REPLs – see https://github.com/seancorfield/dot-clojure/blob/master/deps.edn#L59 for examples. I personally like to start a Socket REPL (clj -A:socket) since I use Atom/Chlorine which doesn’t need nREPL.

I read the very well written guide. It is very clear.

I’ll need to install correctly homebrew, then a full-fledged flavor of Java, CLJ (or Leiningen) and set the right path and environment variables. I’ll give it a try. I never installed Java and that will be the first big challenge as homebrew seems to have an installer.

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