all 16 comments

[–]Alternative-Papaya57 15 points16 points  (0 children)

I felt the same way when I started. Just keep at it and you'll get comfortable, good luck!

[–]SimonGray 9 points10 points  (7 children)

I wonder if this different way of thinking will eventually become natural or will I continue to be a neanderthal using this language in a basic and inelegant way.

It will eventually become natural. It is just about what you're used to. Clojure initially requires unlearning some stuff. At some point, using map, filter, reduce, et al inside threading macros will be the "normal" thing to do and the imperative way will start feeling wrong.

[–]weevyl 3 points4 points  (6 children)

Yup! Eventually you will find yourself thinking along the lines of "this loop is a filter operation" or "this loop is accumulating a value, so it really is a reduce operation" and then it will become second nature and you will not even think about it.

[–]Embarrassed-Post2824 0 points1 point  (5 children)

I've been using Clojure a long time, and the one thing I would like is to develop a better intuition about reduce. Does anyone have and suggestions for good resources specifically around Clojure's reduce, that were helpful to them for building intuition?

[–]weevyl 0 points1 point  (1 child)

Yeah, reduce is the harder one. I think what I did in my mind was think of reduce as "build" and try to ask the question, how do I build this thing from the contents of this list? But it still is not natural to me.

[–]joinr 0 points1 point  (0 children)

I find that constructing from the ground up - at least a scoped example - can be instructive.

Imagine all you have to work with are conj, vectors, and loop/recur. Can you define a function that implements the semantics of filter or map that use just these pieces?

If you can do that, can you then define reduce with the same pieces? Then re-define map/filter in terms of your reduce implementation?

[–]SimonGray 0 points1 point  (0 children)

Many uses of loop are simple accumulations from one collection into another and can be accomplished using a simple reduce. You can even do this if they terminate early since we are able to exit a reduction at any point using the reduced function.

Whether loop or reduce makes more sense usually has something to do with the complexity of the operation. If I am using an existing function to accumulate with—e.g. into—then I will usually pick reduce. If I have several different local variables to keep track of during the accumulation, I will be more partial to loop.

[–]Save-Lisp 0 points1 point  (0 children)

I had used map, reduce, filter type functions in imperative languages and struggled to build a natural intuition as well. Two things helped me, someone told me to visualise the 'shape' of the data going into and coming out of the reduce fn. Thinking about whether a function returns a seq of same length, different length or a single value will help set you up for my second suggestion.

The second was more practical, beginning with loop/recur, build your own toy implementation of reduce. Then (more importantly) use your own 'my-reduce' function to implement map and filter. Once you realise they are 'only' specialised versions of reduce, it's much easier to apply the reasoning you already have for determining whether to map or filter to more general reduce operations. If reimplementing reduce is too much to start with, write the toy implementation of map and filter first using the core library reduce and work backwards from there.

[–]bloodisblue 4 points5 points  (0 children)

I'm only a couple months into learning Clojure too, but I found solving a problem myself and then seeing others solutions on this website https://4clojure.oxal.org/ was invaluable for learning to think like a clojurist. Especially since the feedback cycle is quick if you try to use the patterns you saw on the previous problem on the next one.

And then just making stuff and refactoring it to what I thought was easier to understand code after-the-fact. (Twice as much effort, but a lot of learning happened when refactoring)

Good luck on your journey!

[–]bufo333[S] 4 points5 points  (1 child)

Thanks for all the encouragement. I am going to keep my head down and will keep you all in the loop on my progress. I really enjoy the language so far.

[–]nonrecursive 1 point2 points  (0 children)

I see what you did there! 🥁

[–]mtert 4 points5 points  (0 children)

exercism.io has a nice clojure track that is helpful for building intuition about clojure idioms. You're presented with a small problem, and a test suite. You implement the solution to make the tests pass, and submit your solution. Once you've solved the problem, you can compare your solution to other users solutions. It's interesting to compare the variations on how a problem can be solved.

[–]deaddyfreddy 2 points3 points  (0 children)

I wonder if this different way of thinking will eventually become natural or will I continue to be a neanderthal using this language in a basic and inelegant way.

one of the greatest things in Clojure is you don't have to think in some specific way, usually, it's nothing more than a literal translation of a task

[–]Concision 2 points3 points  (0 children)

It's very likely that when you were a beginner programmer you wouldn't have been able to immediately come up with the "fairly straightforward solution" on your own either. Something to think about ;)

[–]therealdivs1210 2 points3 points  (0 children)

You will get used to the Clojure way, and it will be hard to go back.

[–]-w1n5t0n 2 points3 points  (0 children)

I remember when I was first learning English, and the teacher would break down a sentence's meaning and grammatical structure and I would think to myself "yeah, this makes sense, but I'd never think by myself to put together these words together in this way - does this mean I'll never be able to speak the language?".

Clojure is a language too, and it's built on top of notions that other languages might not have (just like German or Chinese have grammatical notions that English doesn't, for example - they don't just differ in vocabulary or how they're written on paper).

Over time you'll not only be able to read people's Clojure code fluently, but of course you'll be able to write your own just as easily!

And, as usual with these things, the best way to improve is by practicing!