Not only is it not inherently hard to learn, it's arguably one of the easiest syntaxes to learn. ( fn-name param1 param2 ... ) is the syntax.
Once the brain grasps this, a whole layer of complexity just vanishes. Furthermore, not having to use punctuation between items is just heavenly. There's so much less noise compared to Python, and Python isn't even a particularly noisy language.
Only if you don't consider a forest of parens to be noise. I do. I'm sure I could get used to it after a while, but at first glance, Python code is definitely cleaner than Lisp.
"Forest of parens" can be intimidating for sure, but if it's really a forest, then it usually means there's too much nesting. Which is a problem for any language/syntax. Overnested Python code is hard to grasp, and wide fields of whitespaces doesn't make it better than deep forests of parens/curlies, or mounting slabs of begin/end pairs.
Maybe. As someone with a Lisp background moving to Python (day job), all the semantics hidden behind whitespace makes me just a bit nervous. The parens, for me, make structural editing easier and also give a means of keeping the syntax around even when the whitespace gets damaged by whatever editing operations are happening.
(But whitespace sensitivity has always struck me more as a way to enforce specific whitespace conventions than anything else, and even as far back as Pascal I've been religious about maintaining indention in code. It's easy to do with a decent editor (or not) and helps the readability immeasurably.)
It's not a "forest of parens" any more than any language with C style syntax is, they're just in different places (the correct places) and there's no need to distinguish with braces (which you shouldn't need to).
That’s not true. When you’re passing functions to functions inside functions that return functions... it’s a nested mess.
I studied Lisp and Scheme at university and that’s where it had to remain for me: academically entertaining mind puzzles in data structures and algorithms. It’s just not productive or easily graspable from one coder to another.
Tasteful macros can alleviate this, and Clojure's std lib has a few which are just delightful.
The following does exactly what you'd expect, and there are even cooler ones like `some->` or `as->`.
(->> some-nums
(map square-root)
(filter even?)
set
count)
This is what lisp buys you, dead simple rules for syntax, with the option to add syntax with macros. If you made a mistake in syntax design, deprecate the lib and make a new macro, it need not be a feature of core language for all eternity.
And then you use a threading macro to assemble a middleware stack, only to find out that the middleware is applied in reverse order of what's listed as an inbound request comes in... (The outermost middleware being listed last in a threading form).
There's a reason for it, for sure, but it's surely a part of the learning curve.
Yep, it's always possible to have a mismatch in assumptions. That one definitely bit me as well. What's important is that the learning curve is not due to arbitrary rules, it's a faithful application of the logic of the macro.
Remember that what is being passed through the threading macro is not the request, but the handler function itself. Each middleware takes the old handler, wraps itself over it to do things before and after the old handler. The threading macro is not a representation of the path your request will take, it is a way to build up a chained function that represents your final handler, which will then receive the request. Suddenly the ordering makes perfect sense :P
Once the brain grasps this, a whole layer of complexity just vanishes. Furthermore, not having to use punctuation between items is just heavenly. There's so much less noise compared to Python, and Python isn't even a particularly noisy language.