Ever wanted the speed of Python plus the readability of Lisp/Clojure?

If you said Yes, well, look no further! I present to you the Hy language.

Hy is a Lisp dialect that translates itself into the Python Abstract Syntax Tree.

Pretty cool huh? Soon enough I should come up with a simple Jupyter Notebook for exploring what this language has to offer.

For now, I’ll leave you with the classic FizzBuzz exercise, so you can get a sense of what the language looks like first.

Oh but there’s a twist. I implemented it in two “unusual” ways.

In the first one I went for a “Divide and Conquer” (sort of) approach.

;; The only way to tackle such a complex problem: Divide and Conquer (sort of).
;; You can call fizzbuzz with debug = True if it helps you grasp the solution.
;; Author: @atgmello

(require [hy.contrib.walk [let]])
(import [math [floor]])

(defn fizz-buzz [until &optional [debug False]]
  (setv result (list (range 0 until)))
  (defn devide-fizz-conquer-buzz [ini end]
    (if (= ini end)
        (let [res (list)]
          (do
            (if debug
                (print (.format "Leaf reached.\nValue: {}\n" ini)))
            (if (zero? (% ini 3))
                (.append res "Fizz"))
            (if (zero? (% ini 5))
                (.append res "Buzz"))
            (if (zero? (len res))
                (.append res (str ini)))
            (setv (get result (- ini 1)) (str.join "" res))
            (if debug
                (print (.format "Results so far:\n{}\n" result)))))
        (let [pivot (floor (/ (+ ini end) 2))]
           (do
             (if debug (print
                         (.format
                           "Dividing:\nIni: {} Pivot: {} End: {}\n"
                           ini pivot end)))
             (if debug (print
                         (.format
                           "First recursion:\nIni: {}. End: {}\n"
                           ini pivot end)))
             (devide-fizz-conquer-buzz ini pivot)
             (if debug (print
                         (.format
                           "Second recursion:\nIni: {}. End: {}\n"
                           (+ pivot 1) end)))
             (devide-fizz-conquer-buzz (+ pivot 1) end))))
    (return result))
  (for [n (devide-fizz-conquer-buzz  1 until)] (print n)))

(fizz-buzz 100)

The second one is a type annotated, parallel code. And it’s actually a lot cleaner than the first one. This goes to show how parallelizing embarrassingly parallel code is trivial using some functional programming concepts. Doesn’t mean you should always do it, though.

;; Type annotated, parallel implementation of the fizzbuzz problem.
;; Author: @atgmello

(import [concurrent.futures [ProcessPoolExecutor]])
(import [os [cpu-count]])

(defn fizzbuzz? [^int n] (zero? (+ (% n 3) (% n 5))))
(defn fizz? [^int n] (zero? (% n 3)))
(defn buzz? [^int n] (zero? (% n 5)))

(defn check-which [^int n] (cond [(fizzbuzz? n) "FizzBuzz"]
                                 [(fizz? n) "Fizz"]
                                 [(buzz? n) "Buzz"]
                                 [True n]))

(defn fizzbuzz [^int n]
  (setv ^ProcessPoolExecutor executor
        (ProcessPoolExecutor :max-workers (cpu-count)))
  (setv ^list res (.map executor check-which (range 1 (+ n 1))))
  (.shutdown executor)
  (for [r res] (print r)))

(fizzbuzz 100)

You can check these and other crazy FizzBuzz solutions over at:

Submit yours as well! :)

PS: The credits for the joke in the first paragraph goes to @hlissner. Btw, if you use Emacs (or plan on doing so), you should totally check out his Emacs distribution, Doom Emacs. I’ve been using for quite some time now and I highly recommend it!