Stuart Sierra, a Clojure developer, writes about Clojure style, performance pitfalls and software design.
Commenters cite his articles on threading macros and Clojure community attitudes, and his Thrift versus Protocol Buffers comparison.
The problem is, and I think in the case of Github he makes his rationale plain and clear:
> I don’t think it would be right for Emacs to use github.com. I don’t even think it is right for ENSIME to use github, but I’m scared of moving in-case we lose contributor momentum. The FSF gave github.com a bad score and it’s not libre, which makes me nervous.
This is what scares me about the power of GH too. But let's be honest, as this came up with Stuart Sierra yesterday as well in his post on open source rewards stupid bug fixes and not hard work.
https://stuartsierra.com/2016/07/18/apathy-of-the-commons
If the work is boring, people won't do it.
A corollary: if the tooling sucks, people avoid the tooling, and then things stay on the backburner and never complete.
I hate the whole Slack/Gitter/IM channel as well, but the idea of avoiding tooling (e.g. git), which did take Emacs forever, leads to far less contributors like me.
Can we at least work on documenting contributor workflow? How do I build an Emacs test environment and harness system? These things must be bookmarked to emacs-devel and other mailing lists on MARC archives and what-not, as I have yet to find even good blog posts (not that I say that as a standard, but in this case more of what I don't want) of how to set this up.
I do not expect a Github wiki linking to a Gitter channel about setting up a Docker dev containter for emacs-25.x, but can we at least have better tooling for pulling from git repos and…
I like the suggestion in namespace aliasing in https://stuartsierra.com/2015/05/10/clojure-namespace-aliases:
As a general first rule, make the alias the same as the namespace name with the leading parts removed.
(ns com.example.application
(:require
[clojure.java.io :as io]
[clojure.string :as string]))
Keep enough trailing parts to make each alias unique. Did you know that namespace aliases can have dots in them?
[clojure.data.xml :as data.xml]
[clojure.xml :as xml]
Eliminate redundant words such as “core” and “clj” in aliases.
[clj-http :as http]
[clj-time.core :as time]
[clj-time.format :as time.format]
Then you can see immediately what `d` is...
Namely:
(require '[dk.ative.docjure.spreadsheet :as spreadsheet])
(You would still not know the library and might have to ask the same question, but it makes more sense.)
About `d`:
There are always exceptions. For example, some namespaces have established conventions for aliases:
[datomic.api :as d]
the code doesn't need anything, people reading it do. Names are useful because they make intent explicit. Point free programming in functional languages is often overused. Stuart wrote a good blog post about this a few years ago.
"All too often, however, I see the threading macros used in places where they make the code less clear. Early in Clojure’s public existence, there was a fad for “point-free” programming, a kind of code golf without any local variables. This is a fun exercise, but it does not lead to readable code, and I’m relieved that the enthusiasm for this style has worn off. What has remained is a tendency to use threading macros any place they can be made to fit. I think this is a mistake. Rather than making the code easier to read, it makes it harder, forcing the reader to mentally “unwind” the syntax to figure out what it does."
https://stuartsierra.com/2018/07/06/threading-with-style
I agree with most of the recommendation in this article (thanks for publishing it!), but the advice about futures should be taken with a grain of salt. You need to be careful with futures because they swallow exceptions. However, the solution given (setting a global exceptions handler), while sound advice in general, doesn't actually solve the problem of hidden errors, as futures catch all exceptions and return them (so the caller can handle the failure in whatever way it prefers).
If your goal is "fire and forget" behavior (e.g. sending off a confirmation email), then it's better to use java.util.concurrent.Executors directly. It's actually easier than it sounds: https://gist.github.com/pesterhazy/c41786690ee0f8a3e5a21f88fa4a486a. Also see https://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions
Just to add some reference to why it can take a long time to start a REPL (for example):
> As it turns out, Clojure start time is a complicated and multi-dimensional topic. Clojure projects are slow to start not only because of JVM — JVM itself starts in ~50 ms — but because of JVM specifics the classes are loaded slowly. Clojure projects are slow to start not only because of Clojure — Clojure itself starts in ~1 second — but because of Clojure specifics, the namespaces, especially not AOT-compiled one, are loaded slowly. And so on.
http://clojure-goes-fast.com/blog/clojures-slow-start/
A more recent comparison of Clojure, Java and some other Clojure-inspired languages:
https://stuartsierra.com/2019/12/21/clojure-start-time-in-2019
I haven't done any GUI's in clojure, but i think swing is best doc'd, stuart Sierra series:
http://stuartsierra.com/2010/01/03/doto-swing-with-clojure?0.004707886526261973
http://stuartsierra.com/2010/01/02/first-steps-with-clojure-swing
--------------------
or SWT:
http://berlinbrowndev.blogspot.com/2009/02/doing-it-wrong-fun-with-clojure.html
http://www.li-am.com/2009/08/button-in-eclipse-swt-clojure.html
http://www.li-am.com/2009/08/swt-is-alive-from-clojure.html
http://www.li-am.com/2009/08/jface-examples-in-clojure.html
----------------
there's also bits on Qt and JWT, search for them