Productivity brought by Clojure [slides]
slideshare.net
slideshare.net
Clojure is amazing and i can't recommend it enough. I wish more people looked past the unfamiliar syntax and understood why it exists and how it makes you achieve more with simpler code.
Likewise, each function page (if you scroll down) has a "See Also" which lists similar functions, which helps discover other functions in the standard lib.
Beyond the Standard Library, I find the Luminus Project [2] an excellent source of real-world code and documents for problems around web development. Further along these lines is the Clojure Cookbook [3] as well.
[1]: https://clojure.org/api/cheatsheet [2]: http://www.luminusweb.net/docs [3]: https://github.com/clojure-cookbook/clojure-cookbook
> "lightbulb moments" for a dev steeped in C-like languages?
I'm from C++, so I feel what you mean when moving from Imperative to Functional. I have two insights that helped me:
* Despite the huge type systems, languages like C have "Raw Memory" as the universal data structure. Think about pointer magic or the `union` type. Clojure does something similar; Despite the different data structures, the universal structure is `seq` which allows iteration over a data structure in the same way pointers iterate over any memory.
* Clojure's immutable data structures eliminate the Pass-By-Reference and Pass-By-Value dichotomy. As such, you aren't so much (with functions) altering memory as transforming data. It feels much more like math (especially Linear Algebra) where you are transforming data. Seeing my code as a series of transforms greatly helps my understanding of a piece of Clojure code.
The main example I work through is in JavaScript so that Clojure's syntax doesn't get in the way (I love s-expressions, but they're not the point of the talk).
[1] https://www.braveclojure.com/clojure-for-the-brave-and-true/
Using let can also be a decent crutch, if you're just not used to doing things with functional composition and (occasional) macros.
I truly doubt many professional devs are put off by the syntax. This is the least of the hurdles facing any (post-beginner) programmer learning a new language. It wouldn't even make it to the bottom of my list of criteria.
But also unfamiliarity in general is a hurdle. Clojure is unfamiliar in a multitude of ways and it takes some effort to realize how all these things Clojure is different in actually have great synergies.
I think Clojure will be fine. It is slowly and steadily growing. I honestly think it has reached well beyond the point where it can fade away. People always bring Common Lisp as an example and mention so-called "Lisp curse", etc. but if you follow and analyze the history of PLs - you'd probably realize - Clojure is a natural next evolutionary step of Lisp.
The industry desperately needs languages like Clojure and Haskell. Haskell being somewhat more "academic" and a bit "impractical" (I should emphasize the double quotes: Haskell in the right hands can be extremely, dangerously practical) never going to reach the status of a mainstream language, whereas Clojure just might. Realistically, it probably won't ever become top ten in TIOBE (or whatever similar) index, and that is totally okay. But it is pretty good already, and it is arguably better than Python and Ruby, Java, Javascript, Go, C#, etc. Clojure is Haskell's "worse is better".
And look: it already has more conferences and meetups (more than Elixir, Elm, OCaml, Haskell, Groovy, maybe even Scala) around the world (almost every European country now has its own seasonal Clojure conf.), it has over a dozen of books (and more coming), more podcasts. Clojure is a niche, but it is slowly become more popular.
I find Python in the REPL to be great, but I think Common Lisp with Slime and maybe Clojure with Cider take it to a new level. You can write your code and when it errors out it drops you into the REPL where you can update the code incrementally while it is running.
If Python gets me X% increase, Lisp and Smalltalk (and maybe Forth) get you some X% + Y%. The parent comment is right that 30% is probably a back-of-the-envelope calculation and not a rigorous one.
I'm only a novice/superficial language geek, so I can't tell you why Lisp and Smalltalk can do that though. Extreme late binding? Hopefully someone more educated can reply.
That's part of it. That resulted in any given code change in a method usually requiring the recompilation of just one method. Much of the Smalltalk class library was fairly stateless-ish, so you could unwind the top one or two stack frames and restart about 90% of the time.
I'd love to know if anyone has a way to get it to work because I really miss REPL based development from my common lisp and Clojure days.
Initially, it wasn't clear for me what editor is used but it appears to be Vim/Neovim with Fireplace: https://github.com/tpope/vim-fireplace
Actually looks pretty simple and straightforward. There is a healthy choice of different editors and IDEs for Clojure right now, thanks to building on common foundations of https://github.com/clojure/tools.nrepl
I could not grasp several error messages, took me a long time to write something to a database and it didn't really feel at all natural to me. But I guess you'll have to get used to the functional nature, but I don't believe all the hype about functional programming in general.
If it was so effective as people seem to claim, I am sure everybody would use clojure. My experience is rather the reverse, it is harder and takes a long time to develop in. Maybe it's more predictable and is better software with less bugs in the long run, but I wouldn't really know since I lack the experience.
A lot of programming languages today, like javascript, already has functional stuff within it. I get the appeal for it, but I'm not sure it's the best tool for every job or even most stuff.
If anyone is willing to post a youtube-talk or something that can convince me of otherwise, please feel free.
Whatever you might think about the qualities of Clojure, the above is almost certainly false.
I don't think this is even remotely true. As much as everyone in this industry wants to believe it's fast paced and fast moving / evolving, it's hellishly slow in picking up on good ideas and will waste an exorbitant amount of time on bad ideas...
Cool / Hip seems to be valued more than quality when it comes to languages / frameworks while the actually useful slowly, painfully slowly, trickles down.
Java was certainly the fad dejure in it's time, OO was the craze and Java had just been dumped out on the internet, by Sun, for free. In a time when a good portion of compilers costed money (especially if you where not on an Intel based PC), you could learn Java for the price of an internet connection.
c# was the cool kid if you where a Windows developer, Microsoft was looking to update their aging development stack and give themselves hardware portability, so they basically created the JVM for windows in the form of .NET . To ensure that people switched over they kicked the legs out of VB6 and pretty much forced everyone to the new dev stack. They offered a host of language that you could use to write windows apps, but they conformed all of them to the OO style that was popular at the time. With that said, VB.NET did not look like VB6 it looked a whole lot more like C# with VB syntax. So given that developers had to pretty much learn a new language even if it had familiar syntax most opted to just go ahead and learn c# as Microsoft was pimping c#.
Python is the odd ball in your list as it kind of languished for a while. It was not obscure but it was more like Ruby, it had it's devotees but was rather flat, not obscure just flat. That being said, it did have it's cool kid, day in the sun and that was when Google started using it heavily. The AI winter really killed LISP as "the" AI language and there really was no heir apparent, that is until (IIRC) Google started producing some of their machine learning tech and they implemented it in Python. This instantly made Python the cool kid and people started adopting it. My opinion is that Google felt they where too heavily invested in Java and thus needed to diversify into another language. At the time there where not a lot of options that had the combination of mature enough/without legacy clutter/availability of developers, to make the cut, that is why I think Python made the short list.
TLDR: the GP poster is right, popularity and trends have more to do with language adoption than technical merit does.
Blasphemy.
Yeah, but there's more to it than just that. You can find bits and pieces of good things in Clojure that influenced other languages, but in Clojure, they just feel right. Take, for example, immutable data-structures - there were many attempts to implement them for different languages, but somehow the way how they work in Clojure just feels subjectively better. Or the REPL. Of course, you'd say: Javascript has a REPL, Python has one, etc. But if you dig deeper, you'd find out that Clojure's REPL is somewhat better (it is hard to explain, one has to experience what makes it better). Standard library: Javascript is like a complete meth-head here - there's folktale, crocks, sanctuary, ramda, fantasyland, lodash, lodash-fp, immutable.js, etc. and you know, sometimes "more" is not necessarily "better"; Python's praised batteries can also be pretty frustrating. Whereas Clojure's standard library somehow feels much nicer and has a minimum amount of surprises. Stability of the language is almost legendary. Migrating a project from one version of Clojure to another won't cost you your leg.
Yes, Clojure is not a silver bullet (there's no such thing as "the best general purpose PL"), but it's specifically designed to minimize the frustration. And if you felt different, you probably haven't had enough exposure to it.
If you can use a runtime with gazillions of man-hours invested into making it better, and get easy access to bazillions of native libraries, why not?
Note that this same comment argues for Electron.
> a runtime with gazillions of man-hours invested into making it better,
"Man-hours" are such a non-measure of productivity that the classic software engineering book in our industry has a title that declares them a "myth".
The JVM turns out to work fine for functional languages like Clojure, but from my perspective, there's no inherent reason it necessarily should. There's a huge impedance mismatch, as Clojure is not much like Java, and the priorities are completely different.
Bragging that some C program has had a gazillion people work on it means either it has a gazillion special cases (not an advantage), or it has a gazillion bugs fixed (most of which were probably caused by using a low-level unsafe language like C in the first place). Yay but ouch.
(Implementing a new programming language is also typically a vast and complex task, but Clojure has an impressively small number of contributors. When you think through the design first and focus on simplicity, you don't need a gazillion special cases.)
Coming from the Common Lisp world, there's gobs of pure-Lisp programs and libraries I've used which are absolutely a joy to work with, at every level. They don't need many contributors because the code is drastically shorter and simpler. There's lots of Lisp libraries with only a dozen commits, which haven't been touched in years, and a version number way less than 1.0, which work great. That's all they need.
> and get easy access to bazillions of native libraries,
I can see why these can be important when bootstrapping a new language environment, but in practice, beyond version 1.0, I really don't care about them at all. The interfaces I use from Clojure tend to be "return a function", or even "return a function which returns a function". No Java library is designed like this. They're designed around mutable classes, which makes them pretty awkward to use from a functional language. I'll go find a 100-line native Clojure library instead, and by now, there's 100-line native Clojure libraries for almost everything I need.
For another example, the numeric tower is part of the core of Common Lisp, so it's usable from anywhere. BigInteger is a library in Java, and Java still doesn't seem to have rational or complex types, so Clojure does the best it can, but anything beyond fixnum arithmetic is basically opt-in, and almost no libraries use it.
Debugging is even worse, because while there are a million google hits for "java library X", and a thousand hits for "lisp library Y", there's often almost no hits for "java library X with clojure". I have to mentally translate the Java X solutions into Clojure, and figure out any JVM/Clojure interop issues myself from first principles.
That said, Clojure overall works great in practice, and for the most part you can ignore the JVM and its issues. But any time I'm forced to become aware that the JVM exists, my life ends up being worse than the equivalent scenario in the turtles-all-the-way-down world of other Lisps.
You mentioned Common Lisp: it's a good example. I found bugs and limitations in CL runtimes and was several times in a situation where it was clear that I was the "only user". I do not want to be in that situation.
BTW, CL people often say that one should get a paid Lisp because of support. I did (AllegroCL) — and Franz people were really nice, but couldn't find the problem, and I couldn't dedicate the time to hunting it down and providing debugging information. Support doesn't mean that your bugs get fixed.
The JVM is not perfect, but its usage scale matters and means that in general, you are not likely to hit a JVM bug.
As for the JVM, I would be curious to know why it's a turn off. It has been worked on for decades and powers mission critical systems everywhere. Unless you are doing something where the size of the VM matters, or where GC as implemented in the JVM is a non-starter I'm not sure why it matters.
Additionally, there's a CLR version of Clojure as well [0] and I'm surprised that doesn't pop up very frequently. It seems to have a fairly active community around it as well [1]. I haven't looked into it yet, but I intend to once I'm more familiar with the JVM version.
[0] https://github.com/clojure/clojure-clr [1] https://groups.google.com/forum/#!forum/clojure-clr
That said, some do, and the maintainers are active, so I'm sure it works well if you had reason too.
There are alternative methodologies and languages that are similar to BEAM and Clojure otoh. Perhaps not comparable to BEAM when it comes to concurrency. Racket + ZeroMQ for those kind of problems, immutability and concurrency, is a very interesting combo though.
Sidenote: You could run on Javascript runtimes with ClojureScript, but given your statement, I don't believe that is interesting to you :)
(My perspective: I am turned off by any language that doesn't have a JVM implementation because I have so much knowledge and trust of that runtime. But I have to acknowledge, byte-code level support for immutability is thin to non-existent).