And so it came to pass that, almost nine years since I started playing with Hylang (which eventually ran this site) and seven to eight years after I decided to move away from it into “vanilla” Python 3 and later make it static, it struck my fancy to take the old Hy codebase and refactor it to use “modern” Hy.
Getting it to a usable state took something like four hours, which I did piecemeal over a week or so in the late evenings.
But Why?
I did it partially because I have been doing some Scheme, partially because I had a few other pieces of code I wanted to refactor, and partially because having the Sushy repository just sitting there on GitHub seemingly abandoned was an itch I’ve been meaning to scratch for a while.
I don’t really give up on anything (yeah, I know, it can be a challenge), plus I needed a “half-way” project to get my mental gears going the way I wanted.
Highly Annoying Details
First of all, it should be said that Hy has had breaking changes pretty much every release. A few of them have to deal with the decision to move some of the most useful things into a separate hyrule
library, but others cut a little deeper (the removal of staples like let
was a big reason why I moved off it a few years back, but it didn’t stop there).
The ->
threading macro and assoc
(which greatly simplified a few things) were easy enough to recover, but all the other little semantic changes took a while.
Python has also moved on, but even though the 1:1 correspondence between the original Hy code and my current site generator has eroded, the bits that matched were still quite similar, and I could reference them when some quirky bugs surfaced.
But if you’re considering revisiting Hy after a long hiatus, let me give you a list of things I had to fix:
- For some unfathomable reason,
if
needs to have two clauses, so I had to change a bunch of singleif
expressions towhen
conditionals. let
returned, but without delimiters between bindings:(let [one 1 two 2] ...)
instead of(let [[one 1] [two 2]] ...)
, which is arguably an improvement, but guess how many of those I had…import
(andrequire
) also similarly changed structure.nil
and booleans had to be translated into their Python norms.*earmuffs*
and associated symbol mapping changed, so I had to get rid of those too.setv
replaceddef
. I nearly defined aset!
macro to make it look more natural, but decided against that and plowed on.- Python tuples are now
#("like" "this")
instead of(, "like" "that")
(also an improvement, but… annoying since(. foo bar)
is still a thing). &rest
and optional argument syntax changed, as did referencing arguments (you now have#* args
and#** kwargs
)- If you’re using decorators, mind the new
(defn [dec1 dec2] function [args]...)
syntax. - Keyword handling for
kwargs
became:slightly "better"
, but, annoyingly,dict
keys can’t be used in the same way.
The Good Bits
Hy feels a lot more finished.
It is still inconsistent, the documentation lacks examples of many things and it still isn’t 1.0 (well, it was, but they backtracked that…), and there is a significant part of me that really doesn’t like the idea of writing code in a “niche” language, but truth be told that after refactoring, the vast majority of my old code worked first time.
And it still feels enough like a LISP for me to be enjoyable (although I also enjoy Python at least as much). But Fortunately I wasn’t writing Clojure or Janet at the same time (just Scheme), otherwise things would have been weirder (especially considering I did this mostly in the dead of night before dozing off).
That said, the code now generally works and can serve a working website, although there are a few edge cases I’m squashing as I step through the test pages I (luckily) wrote almost a decade ago.
And of course it is likely to be subtly broken in multiple places I haven’t gotten to yet. For instance, I’ve apparently broken a couple of Pillow
calls (every other dependency just works after upgrading them to the latest revision, which is interesting).
But regardless of whether the code is final, useful or production-worthy, it has definitely been a fun thing to revisit–although I’m rather curious about what would have happened if I had switched to Scheme instead all those years back…