I recently received a welcome break from doing PhD-like things when I got a message from a friend who is working on the other side of the continent. We talk far to seldom and the break to chat was incredibly enjoyable. Some of the best jobs I have ever had (and the best work I have ever done) have been working with this guy and chatting was an excuse to reminisce and generally tell lies. I doubt I have fought more with anybody when it comes to the best ways to write code or solve problems. We built some amazing applications, brewed some legendary mead (and derivatives), and even designed a recumbent bike. In many ways, there are few people whose opinion I respect more.
Did I mention we fought a lot? When I write “fought”, what I mean is disagree significantly with respect. If I felt that he understood my arguments and he felt I understood his arguments and we both felt our position was better then we would arrive at the curious point where we were both confident that we had two good solutions and honestly believe that either would work. We chose the solution we would use in an almost arbitrary way (selecting one of many possible future directions and weighting the decision based on that, alternating between each of us, or even tossing a coin). Most of the time, however, one solution would be the agreed best solution and would be followed.
Nostalgic reminiscences aside, the reason for the initial chat message was a reminder of one of the differences in our coding styles: I prefer to put my constants first in boolean test statements. My primary language is C++ and I would write the following
if (42 == age) {
instead of
if (age == 42) {
The term coined for writing statements in the first manner is “Yoda conditions.” Although my way (the Yoda way–so you know it must be a wise, effective, short, and green technique) does not read correctly in terms of English, it avoids the possible programming error of mixing the assignment operator (=) with the logical equivalence operator (==). In my version of the boolean test statement, if I mistakenly only typed on ‘=’ symbol the compiler would signal a compilation error and my stupidity would be noted and a correction would be made
if (42 = age) { // error! - you cannot assign to a constant
On the other hand, if one were to write the statement using the more English syntax and make the same error of only using one ‘=’ symbol the compiler would happily accept the mistake and the boolean condition would always evaluate to true and the variable ‘age’ would be assigned the value of 42 every time.
if (age = 42) { // runtime error! - age is now 42
// and the condition is always true
One would hope that this behaviour would be spotted in the runtime actions of the program and the tester would flag the error which would lead the coder to hunt down the error and fix it. I just happen to like the trade-off between English-ness and immediacy of error detection.
Feel free to insert any rants regarding C++ as a language, my bracketing style, and my ability to type code correctly here. They are outside the point. Actually, I will accept a well-directed rant at me using a numeric constant (42) that has almost no meaning instead of a named literal such as AGE_AT_WHICH_WISDOM_IS_BESTOWED.
But, now there is a way to have the best of both worlds … almost. It comes in the form of some C++ template meta-programming. I have been playing with template meta-programming lately and am enjoying the exercise. When I have some more extra time I will really learn how to take advantage of the practice. The solution is described in the StackOverflow article linked above and it involves using the following snippet that will evaluate an expression to see if it is boolean at compile time and then throw an error if it is not boolean. If it is boolean then no additional runtime overhead is incurred–clever.
struct not_a_bool {};
template<typename T>
not_a_bool ERROR_CONDITIONAL_EXPRESSION_IS_NOT_BOOL(T value)
{ return not_a_bool(); }
bool ERROR_CONDITIONAL_EXPRESSION_IS_NOT_BOOL(bool value)
{ return value; }
#define if(x) \
if(::ERROR_CONDITIONAL_EXPRESSION_IS_NOT_BOOL(x))
#define while(x) \
while(::ERROR_CONDITIONAL_EXPRESSION_IS_NOT_BOOL(x))
A couple of #defines and some templates and boolean expressions are tested explicitly for their boolean-ness. The exception is the ‘for’ loop (the most common loop, unfortunately) that has a three-part block inside parentheses, something that does not translate easily into #define statements.
So, did I change my coding style to use the English-like syntax instead of the Yoda syntax? No. I probably would have if it were not for the inability to test ‘for’ loops. I tried out the code above and it worked exactly as advertised. I even tried to come up with a combination of #define statements and templates that would handle ‘for’ loops but could not come up with anything that would not incur run-time overhead. So, I tossed everything and went back to my Yoda-like ways.
Others have covered Yoda conditions and generally view them as a useful irritation that is worth more than the alternative.
(Low irritation + quick error detection) > (potentially missed logic errors)
So, once again I am left in the position of disagreeing with the person whose technical opinion I value most. Sigh. I am waiting for a C++ compiler (it happens in other languages as well, by the way) that will warn of an assignment and implicit logical comparison where a logical comparison is expected. I will be equally happy with the template-based implicit boolean test that works across all logical expressions in the language. Until then, it is going to be me and Yoda butchering the English language in the quest for perfect translation of idea from mind to implementation.
Google does not appear to embrace the yoda syntax.
https://www.google.com/search?q=what+is+the+answer+to+life+the+universe+and+everything
An intresting way to make sure sneaky bugs dont’ get into the system, if a bit backwards for us anglos.