Written on 2021-08-05
I have once again changed blog engines.
I chose Cryogen as my previous blog engine when I was focusing on Clojure in my day to day. I can no longer say that, so it makes sense to me on principle. I like the idea of being able to work on my blog in my "main" language, in general. But there's something even more than that here, I think.
I've given both Clojure and Common Lisp a fair shake at this point, and I think I've found that I prefer working in Common Lisp. That's not to say I hate Clojure; I'll still be using it with some frequency. I'll certainly reach for it before I ever reach for Java again. But there are a few points that stick out to me, and all came up in favor of Common Lisp.
First, and this is probably the most superficial of my talking points here: I like the way Common Lisp's culture seems to do things. The conventions of the group make more sense to me as a whole. Let me paint a picture.
When I ran this blog on Clojure and Cryogen, I had the following directory structure:
content/ - md/ - post.md - post.md - post.md - css/ - main.css - img/ - favicon.ico (et all) - yewscion.png - cryogen.png deps.edn LICENSE project.clj README.md src/ - cryogen - core.clj - server.clj themes/ - lotus/ - README.md - config.edn - css/ (not listing these folders, but there are files inside) - html/ '' - img/ '' - js/ ''
There are not one, not two, but three different configuration
files. There is both a
src/ directory, with all of my
files living under
src/ containing the source of
themes/ directory has a named theme in it, which itself
has its own README and config file.
It's a very regimented directory structure, sure, but it is also one that carries a lot of ambiguity and redundancy. Which file has this configuration option in it? Is this part of my CSS, or the themes? Did I remember to update the Cryogen project inside this repository, or is it still running an older version?
Basically, I'm trying to say that it is organized differently than my brain works.
Contrast that with what it looks like now, under Common Lisp and Coleslaw:
title.post title.post title.post title.page static/ - favicon.ico (et all) - img/ - yewscion.png LICENSE README.md themes/ - default/ - base.tmpl - css/ - style.css - cc-by-sa.png - logo-large.png - logo-med.png - logo-small.png - index.tmpl - post.tmpl
There is a single config file, which is actually a dotfile:
.coleslawrc is where the config for this Coleslaw site lives. There
are exactly three folders: The parent folder,
themes. All posts and pages (the actual content of the site) go in
the parent folder, and are distinguishable by their filename (I also
start each post's filename with a date, so they are in order and
separated from the static pages).
All content that doesn't need processing (images, favicons, other
binary files, whatever) goes into
static/ and is simply copied over
on deployment. And while there still is a
themes/ directory, it
isn't its own repo: No extra redundant directories, no theme-specific
README or config, and no assumptions of using more than one theme for
If I were to design something like this from the ground up, it would be more like this. It's utilitarian and structured the way my brain works. And from my meager experience with Common Lisp and Clojure, it seems that these observations would apply to many parts of the ecosystems of each.
Clojure has more scaffolding, more encapsulation, more redundancy. You're expected to do it the way they wanted You to do it. Whereas Common Lisp gives You enough structure to get You going, and then lets You decide where to go from there. The difference kind of reminds me of the way Perl used to be, honestly, and in a good way.
Clojure is a language that makes a lot of assumptions for the user: Immutable by Default, It's All Data, Symbiosis with Existing Platforms (VMs, JS). It allows a programmer to do some really cool things because of these choices, and without any oddities needed to facilitate them. But with assumptions come restrictions: If You want to deviate from these ideas, it becomes much more difficult to use Clojure for the job.
Common Lisp, on the other hand, makes remarkably few assumptions for the user: S-expressions, Cons Cells, and... Lists (I guess)? You can, for sure, still achieve everything You can in Clojure, but it doesn't assume You want to do it that way. Heck, the CLOS exists: You don't even need to be functional at all if the job doesn't call for it.
Of course, this increases complexity, especially between different projects. It means You need to approach each new project You contribute to from square one. And onne of the most common callouts I've heard about Common Lisp is that, when You approach a project written in it, You often have to learn the new parts of the language the author may have defined (making the ecosystem more opaque and obtuse to those not used to it).
I recognize that, but don't really mind it: One of my strong suits has always been figuring things out with limited documentation, and then documenting things I've figured out. I would likely do that anyway, even without the culture having a predeliction for it.
But my main point here is that I prefer a language that gives its users the ability to do things in any way they want to a language that forces its users towards a specific paradigm. I've come to learn that that is one of the things I don't like about C++: It does for OOP what Clojure does for Functional Programming.
But, I digress.
I markedly prefer Lisp-2 to Lisp-1. And Clojure (like Scheme) is a Lisp-1.
The idea that each and every symbol can have exactly one meaning, for sure, has its benefits. However, I think the flexibility provided by allowing functions and variables to exist in separate namespaces is much more valuable to me as a programmer than the clarity a one symbol, one meaning relationship can provide.
Having to bend my thinking to ensure I don't name a function with the same name as a variable will make things harder to read, and I don't think that sharp quoting really makes the code any harder to read than it would otherwise be.
I don't plan to give up Clojure.
I actually plan to extend my knowledge and use of Lisps to cover many different Lisps, for different reasons. For instance, I don't plan on finding a Common Lisp inspired Scripting language, especially since both gauche and guile schemes exist and are tooled for that already. I won't be switching to a Common Lisp Based port of Emacs, either.
But when I am starting something for fun, or if I have a choice of language, my first reaction will be to reach for Common Lisp, at least for now.