Rationals in Clojurescript

Last night, I uploaded some code to compute the Voronoi Diagram of a set of points to github. This post is not directly about that code -- I'll write about that when it is completely working – but rather about something that I noticed when I tried to convert the code to Clojurescript.

There are a few things that are known not to work in Clojurescript that work in Clojure: I had to convert calls from lazy-cat to concat, for example. However, the one difference that really broke things for me was the lack of support for rational arithmetic in Clojurescript.

One major element of my algorithm is a test to determine whether a given point is on a given line segment. With integer coordinates for the sites that determine the Voronoi Diagram and the bounding box, everything about this test can be represented as a rational number. Since Clojure gives you rational numbers by default, while Clojurescript simply uses Javascript's arithmetic facilities, the test works in Clojure but not in Clojurescript.

So what can be done about this? Here are some options:

  • Use floats, but more smartly

    Probably the simplest option, here we would not test for equality, but for almost equality. That is, if the distance between two points is a very small number (e.g. a millionth), and all of the input is integer, then the two points are probably the same. This option is obviously not too satisfying from a theoretical standpoint, especially if the small number is hardcoded. I am fairly sure that there has been research to determine what the exact value of the small number should be, but that would take the code out of the realm of simplicity.

  • Implement rationals in Clojurescript

    I am not sure how possible this option is. However, it is currently the most appealing to me. Rational arithmetic is not so difficult to implement, especially in the limited use case that I need it for: I am pretty sure that I could get away with /, *, +, -, and the comparison operators. These are currently implemented as macros in Clojurescript, which means that they take the Clojurescript code and change it Javascript code. This allows the Clojurescript compiler to take the prefix syntax of Clojurescript and change it to the infix syntax of Javascript.

    If we were to redefine the operators to be functions, we might have a chance to run different code given different types of input. The defmulti and defmethod macros seem perfect for this. The major question is whether it is possible to shadow the names of the operators but use them nevertheless. That is, will I be able to add (:require-macros [clojure.core :as core]) to my namespace and then use, for example, core/*?

    The other downside, beyond the potential difficulties, is the fact that the generated Javascript will no longer be quite as pretty. What used to be infix notation will be converted to function calls. Additionally, there will be a fairly high penalty for doing arithmetic – three or four function calls per arithmetic operation (assuming the polymorphic solution I have in mind works) rather than the current single operation.

Conclusion

I am going to try to implement the rationals in Clojurescript first. At the very least, I will learn a bit more about how multimethods work in Clojure.

blog comments powered by Disqus