Tuesday, March 31, 2015

Using juxt to Compute Signed Angular Distances

Juxt is one of those weird Clojure functions that just doesn't make sense until you see it in action. However, once you get it, you love it. This short example shows a great use of the juxt function.

What does juxt do? It creates a function that is the application of a list of functions to a single argument. In simpler terms, a typical function returns one result for one input. In the case of juxt, you create a function that returns n results for one input. The n results are computed from the n functions that you juxtapose.

For example, suppose you need both the cosine and sine x for a given application. You could create two separate variables, like so:
(defn angle->cartesian
"Convert an angle (in radians) to its cartesian vector 
  (let[x (Math/cos theta)
       y (Math/sin theta)]
    [x y]))

However, it is more convenient to juxtapose (set side by side) the two items being computed into a single vector.

Here's a problem that builds on the above to show how nice juxt is:

You are given two angles in degrees and need to compute the signed distance between them. These angles aren't constrained to [0, 360). If the angles are outside of this range, we want to use the equivalent angle within the desired range. Here are a few examples of the desired output:

First AngleSecond AngleSigned Distance

You can probably solve this problem with some combination of mod, rem, and/or quot, but I find it much easier to simply transform the angles to their cartesian vector form and do the math in that coordinate system. Recall that for unit vectors the dot product of vectors A and B is A*B=cos(θ), where θ is the angle between the vectors. Likewise, the sign of the cross product of the vectors indicates the the direction of rotation via the right hand rule. So, I can use dot to compute my angular offset and cross to determine the direction.

With that knowledge, here's my function to compute angular distances:
(defn angular-delta
"Compute the difference between two angles, 
where angles are in degrees."
[a b]
(let [[u v] (map (juxt #(Math/cos %) #(Math/sin %))
                 (map #(Math/toRadians %) [a b]))
      theta (Math/acos (reduce + (map * u v)))
      sign (Math/signum (reduce - (map * u (reverse v))))]
  (Math/toDegrees (* sign theta))))

Pretty slick, eh? Notice how the combination of juxt and destructuring (the automagic mapping of the result to the [x y] vector) both shortened my code and created a single vector structure, which communicated my intent. As an afterthought, let me state that I am only converting to degrees since they are easier on the eyes for most humans. In the real world, I'd leave the function in terms of radians since, in the words of my favorite college math professor, "Degrees are for temperature, radians are for math."

Does this all give the right answer? Let the REPL decide:
(defn angular-delta
  "Compute the difference between two angles, 
  where angles are in degrees."
  [a b]
  (let [[u v] (map (juxt #(Math/cos %) #(Math/sin %))
                   (map #(Math/toRadians %) [a b]))
        theta (Math/acos (reduce + (map * u v)))
        sign (Math/signum (reduce - (map * u (reverse v))))]
    (Math/toDegrees (* sign theta))))
=> #'user/angular-delta
(angular-delta 10 20)
=> 10.000000000000012
(angular-delta 20 10)
=> -10.000000000000012
(angular-delta 350 10)
=> 20.00000000000001
(angular-delta 10 350)
=> -20.00000000000001
(angular-delta -350 350)
=> -20.00000000000001
(angular-delta 350 -350)
=> 20.00000000000001

Ignoring the precision issues, this gives just the right answer.

I hope this provides a nice explanation of how you might use juxt in a real problem. There are many other similar cases where you need to compute several independent variations of an initial value to perform a computation. Whenever you need do to this, use juxt.

If you liked this page or learned anything from it, please tweet the link and/or follow me on Twitter. Your support and interest is the fuel that drives the effort.

Monday, March 30, 2015

Conway's Game of Life - A Demonstration and Postmortem of a Clojure/ClojureScript Project

The Project

I wanted to create an interesting project in Clojure that had the following features:
  • The project should be simple, but interesting
  • The project should demonstrate how Clojure, ClojureScript, and cljx interact
  • There should be some cool Clojure features to learn about
  • I wanted to demonstrate how to achieve state in a stateless world
I chose to program up Conway's Game of Life, a simple zero-player cellular automaton. It's a fun little simulation and meets all of my criterion. Here's what it looks like:

The Rules

  • A living cell with only one or two neighbors dies
  • A living cell with two or three live neighbors survives
  • A living cell with greater than three neighbors dies
  • A dead cell with exactly three neighbors comes to life


Implementation in Clojure

Conway's Game of Life is a cellular automaton in which a population of cells evolves with the following rules:
This project was coded up in Clojure as an example of what can be done using the clj/cljs/cljx integration. It was done in three main files: rules.cljx, swingui.clj, and canvasui.cljs. Below you will find the complete listing of the rules and canvasui namespaces. the swingui namespace is available via git here.

Here's a listing of the entire "rule engine" for the application.
(ns conway.rules)

(defn gen-cell[](if (> (Math/random) 0.7) :alive :dead))

(defn seed-grid [rows cols]
  (vec (take rows (repeatedly 
    (fn [] (vec (take cols (repeatedly gen-cell))))))))

(defn neighbors [[i j]]
  (let [x ((juxt inc inc identity dec dec dec identity inc) i)
        y ((juxt identity inc inc inc identity dec dec dec) j)]
    (map vector x y)))

(defn count-neighbors [grid coord]
  (let [n (map #(get-in grid %) (neighbors coord))]
    (count (filter #(= % :alive) n))))

(defn sim-step [grid coord]
  (let [n-live (count-neighbors grid coord)]
    (if (= :alive (get-in grid coord))
      (case n-live
        (2 3) :alive
      (if (= 3 n-live) :alive :dead))))

(defn step [grid]
  (into [] (for [i (range (count grid))]
          (into [] (for [j (range (count (get grid i)))]
                  (sim-step grid [i j]))))))
Perhaps the most interesting aspect of this project is the amount of code (and I mean the small amount) written to do this complete implementation. I am continually amazed as I write more Clojure about the expressiveness and conciseness of the language. Another thing to point out about this file is the cljx extension. By using this, I can write code that cross-compiles to target both the JVM and the browser via JavaScript. Pretty cool, eh?

Finally, I wanted to point out my favorite function in this program: juxt. the Clojure juxt function creates a function that performs a sequence of operations on a single item and returns that result as an indexed data structure. This is a perfect function for computing the neighbors of a cell in a grid. This is way better than having 8 sequential function calls in which you compute steps to the right, upper right, top center, upper left, and so on.

And here is the complete listing for the canvas UI code.
(ns conway.canvasui
  (:require [conway.rules :as rules]))

(defn draw-background [canvas ctx]
  (doto ctx
    (-> .-fillStyle (set! "#000000"))
    (.fillRect 0 0 (.-width canvas) (.-height canvas))))

(defn draw-and-update-grid [canvas ctx grid dim]
  (let [dx (/ (.-width canvas) dim)
        dy (/ (.-height canvas) dim)]
    (draw-background canvas ctx)
    (-> ctx .-fillStyle (set! "#00FF00"))
    (doseq [i (range (count @grid))]
      (doseq [j (range (count (get @grid i)))]
        (when (= :alive (get-in @grid [i j]))
          (.fillRect ctx (* dx i) (* dy j) dx dy))))
    (swap! grid rules/step))))

  (.-onload js/window)
  (when (and js/document (.-getElementById js/document))
    (let [cells 50
          grid (atom (rules/seed-grid cells cells))
          canvas (.getElementById js/document "myCanvas")
          reset-button (.getElementById js/document "reset")
          ctx (.getContext canvas "2d")]
          #(draw-and-update-grid canvas ctx grid cells) 10)
        (set! (.-onclick reset-button) 
          #(reset! grid (rules/seed-grid cells cells)))))))
Again, it is amazing how few lines of code were written for this demo.

Finally, take a look at how state is managed in the program. Notice that there are no defs (global variables within the namespace) anywhere. All of the state is managed by a single atom (line 25) that is created within the initialization section of the script and is passed to each function. The draw-and-update-grid function draws and updates the grid (as you might expect) while the reset button is used to reset the grid. Since atoms are synchronous, I don't need to worry about any sort of concurrency problems. It just works.

This is a very common pattern in the Clojure world for designing applications. You have three elements:
  1. A set of rules that can be thought of as an API or DSL for your project. These rules consist only of defns or perhaps defs that define constants. They are used to transform or analyze a model. They are completely stateless.
  2. A very small number of Clojure concurrency primitives that manage the actual state of the application. In this case, there is only 1 - the grid atom. You might have other primitives, such as one for preferences, but the number should be small and separated by concerns.
  3. A user interface layer. It could be Swing, an HTML app using ClojureScript, or just a repl.
Coming from a background in 10+ years of Java and then about 6 years of Scala, this was something it took me a while to understand, but now I can't live without. When I got deep into Scala I really loved it, but had the hardest time figuring out how to manage state. With Clojure everything is just baked in.

In Conclusion

I was able to write up a simple cross-platform application in just a handful of lines of code using the amazing powers of Clojure, ClojureScript, and the cljx project. Despite its simplicity, there are some great things to learn from the project. If you want to see the entire project, check it out here or my entire github repo here. I hope you enjoyed this project and short postmortem.

If you liked this page or learned anything from it, please tweet the link and/or follow me on Twitter. I hope to have other projects like this in the future, and your support and interest is the fuel that drives the effort.