In short, the key insight of the blog post is this (via untested javascript):
You can define transforming functions like map and filter via reduce (e.g. foldleft or, for Ruby, inject) instead. For example,
map([...], function (x) { return x + 1; });
Can be written as: // append (x + 1) to the result collection
reduce([...], [], function (result, x) { return append(result, plusOne(x)); });
But notice that, above, we explicitly chose `plusOne` and `append`. If we allow a user to pass in any function instead, then we have a higher-order function: function mapping(f) {
return function (reducing) {
return function (result, input) {
return reducing(result, f(input));
}
};
}
Now we can do: var xform = mapping(plusOne)(append);
reduce([...], [], xform);
`xform` is a transducer.Can someone enlighten me why clojure seems to be the trending language?
More concretely, Clojure's mechanisms for abstraction are both simple and extensible. You can create interfaces (called protocols) for writing polymorphic and efficient code against both your own and existing library classes. Transducers, the topic of the article, are an incredible abstraction that allows you to write powerful transforming functions on sequences of data that are not tied to any concrete representation. This means the same transducers you write will work on lazy sequences, non-lazy collections, and even values asynchronously put on core.async channels (a library for asynchronous programming in Clojure).
I think most languages look weird when you first see them and are unfamiliar with their syntax. But if you give it a chance, the nesting that seems confusing at first might actually come to be something you appreciate.
(Macros give you extra power in extending the language, in ways which a language designer couldn't foresee. Because they're not omniscient; for your domain, you can be the expert, not them. Macros let people add paradigms-as-libraries. You may never write a macro, but you can benefit from those who do.)
Now that I'm proficient, I see those parens as cute little code units. With my code editor, I operate on these code units, not just characters. In contrast, other languages seem to have lots of punctuation in all sorts of weird places. Messy.
You can also use ->>:
(reduce
(filter-reducer even?)
[]
(reduce
(map-reducer inc)
[]
(range 10)))
can be written more clearly: (->> (range 10)
(reduce (map-reducer inc) [])
(reduce (filter-reducer even?) []))One the problems is that you probebly only see the more outthere post about clonure on HN, its selection bias. Most things in clojure are lije in any other FP language.
The reason many people like it is because it brings all the niceness of lisp and FP to a modern production ready VM (JVM).
Other then that the design philosphy of focusing in data and smaller composable languges seams hit a cord with many people. Also I at this point have to mention that the community is quite friendly and the maintainers do a good job at pushing the language foreward.
Also, and this is the reason it pops up on HN, the community does a good job on addopting relativly 'weird' stuff and make it practical like logic programmi g (core.match), reducers, transducers and CPS.
I'm not certain that it is the trending language, however. Many "advanced" functional languages are trending nowadays. These languages tend to include some subset of fast functions, good modules, strong typing, pattern matching, good support for concurrency, generics, higher-kinded types, ubiquitous HOFs, easy lambda syntax, abstract data types, immutability, lack of exceptions, encapsulation of effect, minimization of state, so on and on and on.
Clojure is one of these remarkable for its (a) lisp syntax (b) dynamic typing (c) well-spoken leader, and (d) austerity.
As far as looking like a parenthesis layer cake, that's part of the Lisp "tradition", really. One can look at is as the price you pay for true homoiconicity and powerful macros.
Working with Haskell for a while, "absolute" there starts to seem weird - there is room in "programming language space" for "more pure than Haskell", and some attempts at it. I've not drawn any conclusions yet as to whether anything in that space is practical, but it's certainly interesting.