Saturday, 17 November 2012

Compare and contrast...

So I finally finished my Enigma machine!

There turned out to be a bug in my understanding of the requirements, which took a little fixing. Luckily Mike Koss (whose instructions I was following, having been introduced to them at SC2012) also provides a Javascript implementation against which to test my efforts. A bit of debugging later and I now have two working implementations; one in Clojure and one in Java.

The Java implementation was an order of magnitude quicker to write, entirely due to my greater experience with Java. And while I undoubtedly learnt more writing the Clojure machine, I made an unexpected discovery about the Java language. Its nice to know that even when you feel like you have a good grasp of a language, there is always more to learn. So what did I discover? You can't just use short-circuit boolean operators for conditional evaluation - you have to do something with the return value. For example, the following will not compile as a complete statement:


 obj1.action() && obj2.conditionalAction();

Whereas these all compile fine:

 obj1.action();


 obj2.conditionalAction();


 if (obj1.action() && obj2.conditionalAction()) { /* no-op */ }


 boolean unused = obj1.action() && obj2.conditionalAction();


 if (obj1.action) {
  obj2.conditionalAction();
 }

The last three of those give the required behaviour. Of those, the third and final excerpt is my preferred in terms of clarity of intent. However, as I was planning to use this pattern for rotor rotation in my three rotor Enigma machine, it would need to be extended to a third method call with an additional level of indentation. It seems a shame that my original idea does not compile. It also seems faintly perverse that it was not the functional language that prevented me from easily evaluating an expression for its side effects!

In fact it was academic, as my final understanding of the Enigma machine did not require this logic.

The code is on Git Hub and some statistics are below. While the bracket count is higher for the Clojure implementation (a common complaint leveled at lisp-like languages), it does however surpass the Java version in other measures. (Remember, All Code Is Evil, so less is more!)

Statistics Clojure Java
Characters 1914 2959
Lines 40 107
Functions/Methods 11 12
Parentheses "(" & ")" 77 51
Square Brackets "[" & "]" 21 4
Moustaches "{" & "}" 4 18
Total Brackets 102 73