From Twitter: how do we sell Clojure?

I’m not sure I’m convinced that Clojure must try to dominate “the market”, but inasmuch as this thread is about discussing how to do it, my contribution:

I have had, shall we say, mixed success evangelizing Clojure to mostly-Java developers across several different teams and years of improvements to tooling, libraries, etc., following a fairly set pattern. Unfortunately, I recognize that this pattern doesn’t scale, nor is it amenable to the kind of self-discovery that would be the fastest, best path to widespread adoption.

The approach I take is to get the prospective Clojurist working at the REPL. Fatal uncoolness of the JVM, poor documentation of build_tool, presence of parens – all are irrelevant. Get them up and running, evaluating forms in a file and seeing the results in the REPL (and, where appropriate, in a browser via Figwheel or whatever). Let them play a bit and validate their intuition about what is actually happening in this weird new setup (though, the setup can be less weird/new - Atom for Atom/VSCode users, Cursive for JetBrains users, etc.).

Wait just a moment. Answer any initial questions. Watch them; after a minute or so ask the prospective Clojurist a single question:

“Well? Do you …see?”

Either she will have gotten a faint glimmer of the flow, the joy waiting just under the surface, or she will say something like “…but you could just do this with lambdas in Java 8…” Either way, you have your answer - a new Clojurist for whom things like mastering :cljsbuild or learning parinfer are small costs, gladly paid or …not a Clojurist.

In my humble opinion, Clojure(script) doesn’t already have a good turnkey solution for “do the same sort-of-awful work you’re doing today, but in this new language instead” (as every new JS frontend framework develops right out the gate) because we aren’t selling the same sort-of-awful work you’re doing today.

Clojure doesn’t need a better mousetrap, Clojure needs a way to communicate the experience of no longer being a lowly mousecatcher to earn your daily bread, in a manner that scales beyond interested mentors bootstrapping prospective users to the point where they can be asked “Well …do you see?” I think that’s a pretty tall order for an SPA framework or a CLI tool, but unfortunately I also don’t have any better suggestions.

7 Likes

I’ve written about this before, but here’s IMO what worked for Elixir — not sure if it can apply to Clojure:

  1. A syntax-based illusion of familiarity — the syntax borrows heavily from Ruby, so a lot of Ruby people are coming in, ignoring at the beginning the fundamental differences between the BEAM and RVM.

  2. An official, core-developed build tool (Mix). Takes care of dependencies, running tests, generating scaffolding and a bunch of other stuff.

  3. An almost-official HTTP abstraction (Plug). Almost official means that one or two core Elixir devs are involved.

  4. An almost-official SQL abstraction layer (Ecto).

  5. Most almost-official high-level libraries use macros to keep things easy (and somewhat simple).

  6. An almost-official, monolith-like web framework (Phoenix) with support for templates, routes, basic security, distributed web socket support, some default JS stuff. Flexible enough to customise, opinionated enough to get you started.

  7. A widely accepted deployment story (Distillery) — allows you to build a tarball that can be extracted onto a server and start.

  8. A promise that everything is built on the shoulders of giants (Erlang/BEAM/OTP) so you have this weird cool obscure runtime that you don’t have to deal with at the beginning.

  9. A promise of a “safe playground” where you can write your code in a specific way and everything will click together without you having to worry about architecting your app.

  10. A promise of scalability, whatever that means.

(Don’t get me wrong, I think Elixir can actually fulfil those promises for most people.)

If you see the whole narrative, Elixir tries to sell a familiar dev experience on top of proven and powerful tools.

I believe opinionated frameworks are one possible way forward — for example, re-frame gives you a somewhat rigid architecture and a lot of people choose it for that inherent promise.

Perhaps Fulcro is another framework that sells the promise of a full-stack Clojure experience.

Is there a purely back-end framework missing? Something that gives you a rigid architecture and you just write your routes and queries, while also having a story about web sockets, deployment and vertical scalability.

5 Likes

As a non web developer, I feel very different. I’m not even sure I want to attract more JS beginners. Maybe I want to keep beating the average like Paul Graham says :stuck_out_tongue: I’d rather see Java, C#, Common Lisp, Scheme, Go and Scala devs come to it.

I do think Clojure is a hard language. That just makes it not attractive to beginners. You need to know what you’re doing. It’s like a race car, you don’t learn to drive on one or you’re going to hurt yourself.

That said, I’ve mostly promoted it by helping answering questions about it, some blog posts, and evangelizing it at work. My team has almost fully adopted it now. Most our systems were rewritten in Clojure. I’ve helped setup a lot of the tooling necessary to bridge Clojure with my companies internal tools.

I think Clojure lacks success stories. It has a few small ones, but it would need one big one. If Storm had won the war against Spark for example, I think it would have had a big impact. Or if Datomic had the marketing of MongoDB, there’d be Clojure devs everywhere. If OM didn’t need an OM.Next, and all ClojureScript devs had rallied behind it, it could have been Elm.

Otherwise, I blame Emacs for half the unpopularity of Clojure. JVM for 25%, and lack of static types for another 25%.

Nobody likes Emacs who doesn’t already like Lisp. People associate the challenges and bad experience and lack of modern charm of Emacs with Clojure. Emacs is just the worst at first impressions, and thus Clojure is too.

The JVM is unattractive to JavaScript developers. Or to any dev coming from an interpreted dynamic language background like Ruby, Python, etc. If they’re not learning Java, Scala, Kotlin or even Groovy, they sure won’t learn Clojure.

Finally, Java, C#, Go, Scala, C++, D, etc. devs, they can’t understand not having static types. They’ve used Python once, and don’t think it can scale beyond scripts without becoming an unmaintainable mess. Also, they doubt the performance will be good enough for them.

For all three things, we’d need a solution. I don’t know what though.

3 Likes

For a full-stack framework, I personally favour Duct and I think it has potential to grow and become “the” standard framework. It is a very lightweight yet powerful framework that lets you plug in new functionality across the stack very simply. The only downside right now with it being relatively new/early is it lacks great and unified documentation, I often have to explore a few different repository repos/wikis to find certain documentation. I hope (and I’d be willing to help with this) the framework gets a dedicated website with extensive documentation.

One of the weaknesses I find in clojure (and experience daily while trying to bring other devs on board) is spotty documentation. Pedestal, for example, has clickable links to “Crash Course” guides that simply bring you to placeholder templates, which can be incredibly frustrating when you are starting out. There are a couple projects I’ve run across that do it really well though, like re-frame, luminus, cats, official spec guide, duct’s individual pieces, etc.

This boils down though to community effort, we can’t feel entitled to this stuff; all the placeholder guide templates for pedestal are just waiting for PRs to their documentation repo, I believe duct has a doc repo as well. A couple of volunteer hands over a few days could really improve the new-dev onboard experience.

4 Likes

I don’t wont a template with 40+ options… Would prefer more opinionated templates.

I think this is very true. Part of what helped Rails take off was that there were decent official solutions to most every problem you’d run into starting a web app: SQL/ORM, database migrations, auth, filters, testing/fixtures.

It’s much easier to learn when most people are using the same solutions, effectively out of the box – much easier to help coworkers when it’s likely they’re doing it the same way you already know how.

I think part of the issue here is that Cognitect is the “official” source and they don’t build websites/web applications as their bread and butter. And even when they have been building full stack websites, we’ve gotten Pedestal (experimental, poorly documented, mostly abandoned apart from a core library), Om (deprecated/abandoned), Om.Next (still not stable or well documented). It looked like we might get a semi-official framework with Arachne but that seems to have ground to a halt now (and seemed ridiculously complicated and, again, very poorly documented).

I’ve tended to stick to the simple stuff: Ring, Compojure (for routing; although we’ve also used Bidi in one project), Selmer (for templates), clojure.java.jdbc (for persistence, with HoneySQL if I need composable queries). But I don’t build anything full-stack (no JS/cljs) and none of that address security (we have JWT/OAuth2 for one project and Azure AD for another).

I originally ported a lightweight MVC framework that I created for CFML (ColdFusion) – it’s one of the two most popular in that community – but after using it for a while to build a few Clojure apps, I decided that it didn’t bring as much value to Clojure as it had to CFML, because Ring + Compojure + Selmer was already almost everything I needed (and pretty much the entirety of what FW/1 had added to CFML).

7 Likes

Just wanted to put in my two cents as a Clojure beginner, and indicate what worked to hook me into this stuff.

But first, I will say that it was NOT web-frameworks

— sorry about this long self-indulgent background story, but it helps me frame my viewpoint —

In grad school (during the late 90’s), I had been huge on Mathematica and Maple and loved the intimacy of “notebook” programming. Also, I used LabVIEW for years to automate all kinds of instrumentation. Those experiences in grad school stuck with me and informed my tastes about what I want from a programming toolchain/platform. Basically, I CRAVE immediacy and expressiveness: being able to deliver what comes into my mind as a computer program.

Paradoxically, through a series of career accidents, I ended up working as a servlet/EJB programmer back in the day when web development was a giant dumpster fire. Over time, I came to the bitter realization that the type of computing I loved in grad school was long gone and it looked like my work was just going to consist of suffering through one turgid, over-engineered framework after another. I eventually left that stuff for other domains.

Although my day-job since leaving the j2ee world wasn’t “software engineering”, I still make programming a major part of my work. I work as a manufacturing test engineer responsible for automating hardware tests and performing failure analysis. I use C# for “doing stuff” and R for analyzing/visualizing data. To some extent, I was able to regain some of that feeling of “agency” with computing that I had back in grad school. Especially with R, it felt very notebook-like and once I got past the quirks, it started feeling expressive. C# also became really cool once I grasped Linq for querying collections and the concurrency sugar of async/await.

I first heard about Clojure quite a long time ago (2011-ish?) on a now-defunct podcast called “Java Posse”. My way of keeping tabs with the java world was by listening to Java Posse. Anyways, they frequently talked about exotic new technologies, mostly Scala (didn’t like, too baroque) but also Clojure which sounded cool because it was a weird old language, Lisp, on the JVM. I put that on my to-do list and never did anything for years.

Then, I came across the videos of the 2013 Clojure Conj, I had remembered hearing about Clojure on Java Posse, and it was a good time to take a deep-dive in the middle of the night while surfing youtube. There was one talk in particular that REALLY spoke to me: Tim Ewald - Clojure: Programming with Hand Tools. THAT talk expressed EXACTLY what I want from a programming language! After that, I started on a path of trying to learn Clojure. I subscribed to Eric Normand’s wonderful video lessons for a while and now I am trying to get some small personal projects off the ground with the initial goal of using Clojure at work for some of my projects.

The thing that makes Clojure great is not the availability of a “do-everything” web-framework. Not everyone is a web-programmer, there are other types of programming that people do. And what is meant by “sell Clojure” anyway? Does it just mean TIOBE rank? A popularity contest competing with javascript, Java, and C#? Is that really the measure of success?

I think if you want to make Clojure last in the long term and not become a historical footnote (like some previous #1 TIOBE “winners” are rapidly heading towards), it is vital to make it appealing to a broad base of practitioners. That means not just web-programmers, but also data analysts, scientists, computational folks, instrumentation, graphics people, and others who work with specialized domains that can use the power and simplicity of the language: games, music, AI, whatever.

I think it is headed in the right direction. OK, yes, error messages need work, but it seems to me like the community and clojure adoption is moving forward.

5 Likes

Personally think of cognitect more as innovators, they seem to pave the way but then move on to the next big thing leaving it up to the community to continue or base new stuff on what they developed.

Because of om.next we now have Fulcro, an om.next fork: stable, well documented, companion libraries and overall slightly different & better model than om-next (IMO).

Now at work were going with apollo client(only js & python), its just mind blowing how much better & simpler fulcro is. Think a big part of the credit goes to om.next for the innovative ideeas.

From what I know duct is inspired by archane and seems to be really nice.

2 Likes

Is that really the state of pedestal? I think it’s used by Walmart labs, so it can’t be that bad.

pedestal-core is still maintained I believe but the original Pedestal project is not.

The only Pedestal element I would call abandoned is “pedestal-app”, the ClojureScript UI framework, which was shelved when React hit the scene.

The Clojure backend web-server portion of Pedestal[1] is alive and well, and happens to be split into core and libraries, all equally important in the eyes of maintainers.

[1] Formerly called “pedestal-service”, now informally just “Pedestal”.

1 Like

It’s not a popular opinion, but when you aren’t popular already, who cares?

I’m making a full stack web framework on top of ring that aims to be the rails of clojure.

There were a few attempts before which never really took off, and my framework might share the same fate, but I’m hoping that web developers from other languages find coast, try it out and get a quick glimpse into what programming clojure could be like in their existing editors (atom, sublime, vs code) and then maybe move on to something more fully featured like luminus + cursive or emacs if they like what they see.

4 Likes

Have you made any screencasts highlighting specific advantages of coast? I’ve heard people like that sort of thing.

4 Likes

curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
sudo apt-get install -y nodejs

It is indeed not hard, but horrible, because it’s not reproducible and Linux distro specific! :slight_smile:

On the other hand if you are opening yourself up to the dangers of curl | sudo bash,
you might as well install the Nix package manager
with curl https://nixos.org/nix/install | sh.
After that obtaining a shell process, which provides you with node, npm, clojure, clj and lein
on the PATH becomes ridiculously simple, regardless of which OS are you using!
It can be macOS, Ubuntu or Amazon Linux (I have no experience with Windows):

nix-shell -p clojure leiningen nodejs-10_x

It will absolutely not interfere with your existing system, because the PATH is only constructed
ephemerally for this new shell process you just started, eg:

$ nix-shell --pure -p coreutils --run 'echo $PATH'

/nix/store/ckq71kkymh1ji2b44xn80wmr7fmi6wr5-clang-wrapper-5.0.2/bin:/nix/store/bcl9zj60h52p47dy85s326mdrqx52417-clang-5.0.2/bin:/nix/store/5q51r2d0xzs4hi8rb661drpf83mhm4b4-coreutils-8.29/bin:/nix/store/qk4fdnzkr8r0gihgyps7x07cpyffvkmy-cctools-binutils-darwin-wrapper/bin:
...

The software you declared, with all its supporting files and transitive dependencies,
down to libc, are all stored under /nix/store in read-only directories.
These directories have a hash in their name to avoid any version conflict,
even between seemingly identical versions of software, which only differ
in the versions of libraries they are linked against! eg.:

$ ls -lahd /nix/store/*-bash-4.4-p12*
dr-xr-xr-x 4 root nixbld  128 Jan  1  1970 /nix/store/axikcsz4wh2qpi5zmlfsmm4jx8wm8s1g-bash-4.4-p12/
-r--r--r-- 2 root nixbld 4.6K Jan  1  1970 /nix/store/c8adxvdnrsqa6v48hagqfab6iv4l35sb-bash-4.4-p12.drv
-r--r--r-- 2 root nixbld 4.3K Jan  1  1970 /nix/store/djpy3089x8ij20dw5zvwvr2ym8iryhl1-bash-4.4-p12.drv
dr-xr-xr-x 4 root nixbld  128 Jan  1  1970 /nix/store/pkjmwq7sqrvjg7cjiph6hq0khsmfl6p8-bash-4.4-p12/
dr-xr-xr-x 4 root nixbld  128 Jan  1  1970 /nix/store/rjglqbbmg27dwwyyqsnn62jcz6qwxkli-bash-4.4-p12/
drwxr-xr-x 4 root nixbld  128 Jan  1  1970 /nix/store/s8mff1kmnc63b21ybdid2ni0fw7mzy7r-bash-4.4-p12/

Now this process is still not any more reproducible than the apt-get above,
but you can just provide a complete package tree archive (which is around ~10MB)
to nix-shell (via a URL or file reference) and it’s guaranteed it will build the
exact same binaries today and one decade from now.

You can retrieve Nix package tree archives as tarballs of a very specific commit
in the nixpkgs package tree source repo, eg:

https://api.github.com/repos/NixOS/nixpkgs/tarball/1539167d215841a966b8395c1025d66812d63d31

or you can pick a version a combination of all those 6500+ packages in the tree,
which has been tested to a certain degree:

curl -sI https://nixos.org/channels/nixpkgs-unstable/nixexprs.tar.xz | awk '/Location:/ {print $2}'

then feed this package tree into your nix-shell:

nix-shell -I nixpkgs=https://d3g5gsiof5omrk.cloudfront.net/nixpkgs/nixpkgs-18.09pre144939.14a9ca27e69/nixexprs.tar.xz -p clojure leiningen nodejs-10_x

If you give this command to your friends, they will also get a shell
with the exact same software versions, be it today or next year
and regardless what they have, macOS or some Linux…

Since this command line is getting a bit unwieldy, you should just put
this information into a shell.nix file at the top of your projects like this:

# curl -sI https://nixos.org/channels/nixpkgs-unstable/nixexprs.tar.xz | awk '/Location:/ {print $2}'
with import (builtins.fetchTarball "https://d3g5gsiof5omrk.cloudfront.net/nixpkgs/nixpkgs-18.09pre144939.14a9ca27e69/nixexprs.tar.xz") {};

mkShell rec {
  buildInputs = [
    clojure leiningen nodejs-10_x
  ];

  shellHook = ''
    export PATH="$PATH:$PWD/node_modules/.bin"
    '';
}

Then you can just run nix-shell from the directory where the shell.nix file is.

If you npm i -D mocha for example, then you can just run it with mocha.
None of that dirty npm i -g ... nonsense is necessary anymore!

Pro tip: Run nix-shell --pure to drop your default system $PATH
and you will see if you are accidentally depending on something specific
in your global, host OS installation.

Further reading:

  1. Nix Pills — small intro tutorial chapters into Nix and Nixpkgs
    Nix Pills | Nix & NixOS

  2. https://nixos.org/

The argument is that having to learn and maintain one ecosystem is better than having to lean and maintain two ecosystems. It isn’t really about which is better.

Many of us just aren’t pushing the boundaries of, say, what a webserver’s garbage collector can do, so we just want something that increases our developer power and productivity. The desire to avoid the jvm/maven/clojars is not because javascript necessarily has a better answer, it is that as javascript programmers we are already using js tools and would prefer not to add the complexity of a whole new set of tools. For the record, I’ve used all of these tools, but still, I’d prefer one set to two–and I can’t avoid the javascript set of tools when writing a modern SPA.

You are right and Nix is cool. My argument is there are much more Ubuntu users than Nix users. And if someone manages to use nix, he/she would probably know Linux very well and know how to get Node.js installed. :smiley:

Maybe I should emphasise that I’m not talking about NixOS.
I’m just talking about the Nix package manager.
My point is exactly that you don’t have to be a guru to use Nix
AND on top of that your knowledge is OS agnostic.

If you hit some obstacles with Nix in your specific use-case,
you can always go back to solving the problem in an OS / distro
specific way, because having Nix on your system will not interfere
with your underlying OS setup (beyond eating up extra disk space).

Good example from today:
I had to convert a logo sent to me in a PDF file into SVG.
I googled for “open source command line pdf to svg”
Turns out there is indeed a pdf2svg tool, so I just did

$ nix-shell -p pdf2svg  --run 'pdf2svg --help'
these paths will be fetched (5.74 MiB download, 31.79 MiB unpacked):
  /nix/store/2li666k7669n3i8n0wbgda41znxzif6s-libjpeg-turbo-1.5.3
...
Usage: pdf2svg <in file.pdf> <out file.svg> [<page no>]

then problem solved:

$ nix-shell -p pdf2svg  --run 'pdf2svg logo.pdf logo.svg'

Everyone should know at least this much about Nix…

I forgot to mention one more practicality; install a faster, nicer package search utility with
nix-env -i nox, so you can find package names, eg:

$ nox pdf2
1 pdf2djvu-0.9.9 (nixpkgs.pdf2djvu)
    Creates djvu files from PDF files
2 pdf2odt-20170207 (nixpkgs.pdf2odt)
    PDF to ODT format converter
3 pdf2svg-0.2.3 (nixpkgs.pdf2svg)
    PDF converter to SVG format
4 pdf2xml (nixpkgs.pdf2xml)

5 python2.7-pdf2image-0.1.14 (nixpkgs.python27Packages.pdf2image)
    A python module that wraps the pdftoppm utility to convert PDF to PIL Image object
6 python2.7-PyPDF2-1.26.0 (nixpkgs.python27Packages.pypdf2)
    A Pure-Python library built as a PDF toolkit
7 python3.6-pdf2image-0.1.14 (nixpkgs.python36Packages.pdf2image)
    A python module that wraps the pdftoppm utility to convert PDF to PIL Image object
8 python3.6-PyPDF2-1.26.0 (nixpkgs.python36Packages.pypdf2)
    A Pure-Python library built as a PDF toolkit
Packages to install:

Another, maybe even more powerful example:

We wrote a grant application in Notion.
Exported it into markdown and turned it into a professional looking PDF:

nix-shell -p texlive.combined.scheme-small pandoc \
    --run 'pandoc grant.md -V geometry:margin=1in -o grant.pdf'

My colleague did it the 1st time on his Arch Linux, then after I amended the Notion page,
I ran the exact same command on my macOS and got an updated PDF.

You should really give it a try!
Let’s pick the ClojureScript README.md from github for example and see it for yourself what happens!

$ nix-shell -p texlive.combined.scheme-small pandoc --run 'pandoc <(curl -s https://raw.githubusercontent.com/clojure/clojurescript/master/README.md) -o README.pdf'; open README.pdf
1 Like

I have a friend in Shanghai Linux Users Group, and he show us several times Nix. Most things I remembered is he is using a large NixScript file maintaining all his packages across devices. Although I know Nix is powerful in design. I never tried. Thanks for sharing.

Can I use Nix on macOS?

Yes, you can!

curl https://nixos.org/nix/install | sh

(there was even a brew install nix or brew cask install nix but the package is gone now)

We just released this decentralized crypto exchange project recently and it heavily builds on Nix
and we were using both macOS and Linux to develop it:

Whenever anyone updates the package tree URL in the shell.nix we are all getting the new
versions of everything when we git pull. We are not even restarting our nix-shell because
we are using direnv and we have that .envrc file which says use nix

It worth mentioning that the next step is likely going to be introducing ClojureScript to this project :wink:

1 Like

Follow standard marketing tactics? Get an advertisement on Pandora?

“Do you have trouble sleeping? Back pain? Are you ever hungry late at night? Well worry no more… introducing Clojure, the industry proven solution to all your common problems. Proven to work. Proven to last. Software strong. Clojure!” - queue the beautiful men/women and peaceful mountain rivers.

2 Likes