Hands-on Hy - coding Lisp with Python

Timotheus Kampik - 01 November 2017

A rookie's practical introduction to the Hy programming language

Hy is a Lisp dialect that runs on top of - and tightly integrates with - Python.
Considering the rise of Python to the top of many programming language rankings (for example the one published by IEEE) and the rediscovery of functional programming patterns by the software development mainstream, I was curious if Hy succeeds in bringing the functional paradigm to one of the most popular programming ecosystems.

Getting started with Hy

The tutorial in the official Hy documentation excels at providing and overview of the language’s most important concepts and helped me get my first code running in a matter of minutes.
Still, the docs don’t recommend and don’t even mention any tooling that’s available around Hy and I couldn’t find such on my own.
That’s why I decided to use PyCharm as my IDE.

PyCharm allows me to leverage Hy’s Python integration to conveniently run, debug and (potentially) test Hy code.
Because syntactically, Hy ≈ Lisp ≈ Clojure, I installed a Clojure plugin for PyCharm and added *.hy to the list of file types the system highlights as Clojure code. I had to disable inspections for Clojure in the PyCharm settings to not get prompted for any errors.
When I had trouble with Hy’s syntax while programming, I used Lisp or Clojure instead of Hy in my search engine queries.

Implementing a basic neural network with Hy

Now, as we have the basics covered, let’s write some code.
As an example, I picked a basic neural network (gradient descent) as presented by Siraj Raval in this YouTube video and implemented it in Hy instead of Python.

In Hy, we can import any Python library - in our example numpy, which provides tools for numerical programing.
We can also require a set of Hy extensions, so called contributor modules:

(importnumpy)(require[hy.contrib.loop[loop]])

After defining the dependencies, we’re ready to start with the actual neural network implementation.
First, we define a signoid function as our activation function.
Just like in Lisp, in Hy operators are proper variadic functions - and, of course, we need to use tons of parentheses:

;; our sigmoid function, which can also provide its derivative(defnnonlin[x&optional(deriveFalse)](ifderive(return(*x(-1x)))(return(/1(+1(.expnumpy(-x)))))))

And here’s the code that does the actual training.
To implement the training loop, we need the extension we required above.

For advanced, production-like use cases, it is possible to use further tools and services that support or were specifically created for Python.
For example, to enable continuous integration we could run unit tests with pytest and set up a continuous integration workflow with Travis or Circle CI.

Assessment: what’s Hy good for?

Hy is a creative attempt to introduce a highly praised, but sparsely adopted functional programming language to the Python community.
Hy’s Lisp-y syntax and its tight Python integration compensates to some degree for the lack of tooling.
This means that in most use cases, you can’t use Hy on it’s own, but need to use Python to manage aspects like testing and dependency management, and tooling for Lisp or other Lisp-based languages for syntax highlighting.
However, static code analysis isn’t properly possible and will eventually require Hy-specific tooling.

Hy is syntactically more attractive for buffs who already know expert languages like Clojure.
The many parentheses might put off folks who are new to functional programming or know it primarily from modern JavaScript.
Some compromises were made to also support Pythonic syntax, most notably dot notation:

(numpy.mean[15]);; returns 3

Still, I personally would like Hy to draw more inspiration from Python’s syntax and support (significant) indentation instead of parentheses.

All in all, I think Hy brings a refreshingly new (or rather, different) approach to writing code to the Python ecosystem.
If experienced and visible Pythonistas continue to take up Hy, improve its tooling and available learning materials, and optimize its usability, they will encourage its adoption by the broader Python community and consequently boost the prevalence of functional programming knowledge in general.