|Home • Thoughts and Musings • Thomas M. Tuerke on Design • The Truth about Yoda
The Truth about Yoda
|That's not real C!|
|Yes, I know, the blue-sky example, as stated, is not proper C, because of the need for something like |
As I've written elsewhere, Yoda Notation, also known as Yoda Conditions in some circles, is the reversal of operands on the equality operator in C (and derivative programming languages.) The example I provided almost a decade ago,
if("blue" == theSky) ...
illustrates this reversal. This is in contrast to the "normal" way of coding conditionals,
if(theSky == "blue") ...
which has certain vulnerabilities, necessitating the reversal.
Why Yoda Notation?
I've seen a few speculative comments on blogs, conjecturing its benefit as offering some optimization of generated code. This is not true. Equality is a commutative operator, meaning that
a == b is the same as
b == a. Given that, the compiler can take your
b == a and treat it as
a == b if it decides that can generate faster code. So performance is not the reason for Yoda Notation.
Instead, the practice of reversing equality operands—which I've been calling Yoda Notation for quite some time now—is to overcome what some (including me) consider a poor design decision in C and derivative languages, where
=, but the equality operator is
=for equality, and/or contextualize assignment in some way.
The consequence of these factors: it is disturbingly easy to accidentally assign something to something else, rather than compare the two things for equality. In other words,
if(theSky = "blue") ...
is probably not what the programmer intended. The variable
theSky gets assigned the value
"blue" (losing its prior value,) and since that's a non-null value, the condition is always true, making the
if statement pointless (any
else clause will never be reachable.)
Some developers, having been bitten by such a bug—and blowing away many hours of time debugging code that "looks" right but clearly isn't—decided to never let that bug happen to them again, simply by reversing the operatands. Voici: Yoda Notation is born. The compiler knows that you can't assign anything to a constant, and promptly generates an error when you use
= where you meant
==. Simple fix.
Where to use Yoda Notation?
The answer is not entirely straightforward.
Some have a keen distaste for Yoda Notation, and would insist that the correct answer is "never". I won't be so cavalier. I have gone on the record as not liking Yoda Notation, but I don't like writing buggy code, either.
That aside, where "should" one use Yoda Notation?
=and equality is
It means that C# is not a candidate, however. Even though the language has the same
== operators as C, it was specifically designed to not allow assignments within expressions. The compiler will not just treat it as suspcious and warn you: it will outright complain that you can't do that. Still, there are shops that write in both C# and C or C++, and in those places, it's not uncommon for the practice to extend into C# code, simply for the in-house consistency.
Other languages have different operators for assignment and equality, and/or don't allow assignment within expressions.
=, and colon-equals is not allowed within an expression.
=for both assignment and equality, but contextualizes the assignment: you can only do that as a separate statement, not within another expression.
In these languages, Yoda Notation is functionally unnecessary, though it might be used for some of the (admittedly subjective) derivative values: consistency with other codebases, or—as one commenter elsewhere put it—to bring the constant to the front of what might be a long other operand.
Also, Yoda Notation is only required around equality, since it "looks" so much like assignment. It is not necessary for any of the inequality operators.
Beware of using Yoda Notation when one (or both) of the operands has a side effect (say, a "non-idempotent" function or one that remembers something internally, in addition to returning a value.) Order of operation is not always what you think.
Finally, Yoda Notation is moot when comparing the equality of two non-constant items, such as two variables. The compiler can offer no protection from abuse there (and after all, which one of two variables is "supposed to" come first?)
Who Invented Yoda Notation?
The syntax? I don't know. It's been around for a good while, and as I don't particularly like it, it's not me.
The term? No, StackOverflow user zneak did not coin Yoda Notation. I've been referring to the reversed equality operands as Yoda Notation for far longer, so I could make a demonstrably superior claim to authorship. But not losing too much sleep over that, I'm glad that the term took first place in the now de-listed top jargon terms on StackOverflow; that's due in part to zneak submitting the term, and the many StackOverflow readers up-voting it.
Thu Apr 25, 2013 Link to this messageThe Conversation Continues: The Need for Yoda Notation- Thomas M. Tuerke
Pursuant to office-cooler chit-chat, colleague Yin Wang has opined (in Mandarin; see the crude Google translation if you're not disposed to Hanyu...) that the root problem is not so much the assignment operator being the equal sign. He states (and I'm taking liberties with the Google translation, having his opinion first-hand):"I think that using
=for assignment is not really the problem. The real mistake is that C/C++ assignment should not return a value"
He takes the position that the assignment operation should not have been an operator, legal within an expression. It should only be used as a separate statement.
There is merit to that thought, though having assignment be an operator—with all attendant side effects—is actually useful in certain (now perhaps arcane) ways. There is a certain economy of expression permitted by being able to scurry away a value in the midst of a somewhat more complex expression, like a well-placed apposition in a sentence that would otherwise be more awkwardly expressed.
But is that goodness? On the whole, the number of circumstances where in-line assignment really improves the expression of some logic is small; the number of circumstances where assignment was used instead of equality, considerably larger.
I'm not going to take sides in that debate. Subsequent languages have either avoided the issue (by disallowing the construct,) or decided to inherit it (thus joining the fold of languages for which Yoda Notation is useful.) Rational arguments can be made to support both positions.
What I will argue, though, is that like it or hate it, C assignment is what it is; opining and pontification is not going to change that reality. Despite any rational argument in favor of allowing assignment operators, the fact remains that the creators of C designed a perfect storm, making accidental mis-expression of intent far too easy. This is the Sins of our Forefathers I refer to, becoming the genesis of the workaround called Yoda Notation.