Metaprogramming in Hy#

Hy (or Hylang) has been one of my favorite programming languages to play around with. Hy relates to Python like Clojure does to Java; It’s a Lisp-like dialect that runs with a Python and it’s primarily aimed at the easy use of other Python libraries and/or to be easily used by other Python programs.

Python is already a great programming language, so you might ask yourself why you would use another one. There are small differences, but great advantages, like no need for comma’s in list literals and multi-line lambda’s (which you would really like if you think this is essential to get more into functional programming), but in my opinion the big difference and advantage is this: Hy allows you to program the programming langueage itself with macro’s. Like almost all Lisp dialects, it’s ridiculously easy to metaprogram compared to using meta classes or templates in other languages.

“Every sufficiently complex application/language/tool will either have to use Lisp or reinvent it the hard way” - Generalization of Philip Greenspuns 10th Rule

See this example where you can evaluate mathematical expressions like we normally do in other languages.

; Comments start with a ";"

; Mathematical operations with two operands look like this in the
; standard Hy programming language
(print (+ 1 2))  ; This prints the result of '1 + 2'
(print (* 3 4))  ; This prints the result of '3 * 4'
(print (- 12 5))  ; this prints the result of '12 - 5'

; Now let's define a macro which has one argument: 'expression'
(defmacro calculate-classical-expression [expression])

; To turn this expression into a valid Hy expression we need to get the
; operator and operands first. We'll asssume 'expression is a list of
; 3 items' to keep it simple.
(setv
  operator (get expression 1)
  operands [(first expression) (last expression)])
; Now we put these variables in the order Hy can evaluate
; We need to quasi-quote the whole expression with a back-tick: `, so we
; can evaluate parts of the quoted expression
; We unquote different parts with a tilde (~) to force it to be evaluated,
; a list can be unquoted and spliced with ~@.
`(~operator ~@operands)

; now we use our macro to evaluate our classical expressions
(print (calculate-classical-expression (1 + 2)))
(print (calculate-classical-expression (3 * 4)))
(print (calculate-classical-expression (12 - 5)))

Use Cases#

So when would you actually use this? Basically in all cases that involves generating code, which happens when:

  • You’re building a code generator (duh…), for example when code needs to be made based on some configuration or specification.

  • You’re going to write your own domain specific language

  • You’re building some kind of framework

With Hy, you’ll get the powerful paradigma of metaprogramming next to object oriented programming and functional programming. I might dedicate a next blog post to some personal design principles when programming with all these options.