55

Lately, I've been working a lot in PHP and specifically within the WordPress framework. I'm noticing a lot of code in the form of:

if ( 1 == $options['postlink'] )

Where I would have expected to see:

if ( $options['postlink'] == 1 )

Is this a convention found in certain languages / frameworks? Is there any reason the former approach is preferable to the latter (from a processing perspective, or a parsing perspective or even a human perspective?)

Or is it merely a matter of taste? I have always thought it better when performing a test, that the variable item being tested against some constant is on the left. It seems to map better to the way we would ask the question in natural language: "if the cake is chocolate" rather than "if chocolate is the cake".

gnat
  • 21,213
  • 29
  • 113
  • 291
Tom Auger
  • 847

5 Answers5

93

The main reason to do this (so-called "Yoda conditional") is to prevent accidents whereby you accidentally use an assignment operator (=) instead of the equal comparison operator (==).

That is, if you made the mistake of doing:

$foo = 5;
if ($foo = 1) {
  // Stuff
}

The statement will evaluate to true (or, in the case of some languages—like PHP—a truthy value) and you'll have a hard-to-find bug.

But if you did:

$foo = 5;
if (1 = $foo) {
  // Stuff
}

You'll receive a fatal error because you can't assign $foo to an integer.

But as you pointed out, reversing the order generally makes things less readable. So, many coding standards (but not all, including WordPress) suggest or require $foo == 1 despite the bug hunting benefits of 1 == $foo.

Generally, my advice is to follow whatever established coding standard there is, if there is one: for WordPress, that means using Yoda conditionals.

When there isn't, and it's impossible to establish one through consensus with your peers, it's dealer's choice.

Glorfindel
  • 3,137
  • 4
    I remember when designing a language (long time ago) that we specifically made := be the assignment operator (with == for equality test) in order to avoid this sort of trouble. – Donal Fellows May 05 '11 at 23:37
  • I know a few C++ developers who write in this order, too. @DonalFellows - you didn't work on Pascal, did you? I remember that assignment operator from my Delphi days :) – HorusKol May 05 '11 at 23:52
  • 7
    I have written many, many, lines of code, and I have never accidentally typed = instead of ==. The difference is so accentuated everywhere that i've just never got them confused. On the other hand, I have read many pieces of code that are confusing or otherwise hard to understand. As such, I would put the priorities on the readability :).

    Regardless, good answer.

    – crazy2be May 06 '11 at 00:22
  • 7
    Yet another good reason to use -Wall -Werror or your compiler/interpreter's equivalent. There are very few situations where an assignment inside a condition is correct, let alone more readable. A lot of languages don't even allow it. – Karl Bielefeldt May 06 '11 at 03:21
  • 8
    Pedantic: While if($foo = 1) evaluates to true in some languages, in PHP it evaluates to 1 instead; if($foo = 20) evaluates to 20; if($foo = 0) evaluates to 0, which unlike the others is false. This can add a whole 'nother layer of complexity to the bug. – Charles May 06 '11 at 05:00
  • +1 that I've learn that it can be used defensively, though if 1 == $foo looks awkward for me. – OnesimusUnbound May 06 '11 at 09:42
  • @HorusKol No, but my boss at the time had worked quite a bit on Ada. – Donal Fellows Sep 13 '12 at 09:12
  • 3
    Actually, the WordPress Coding Standards DOES call for Yoda Conditionals: http://codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions – Tom Auger Sep 18 '12 at 14:46
  • @TomAuger It seems you're right: judging by the revision history, it was added in December 2010. Not sure why nobody caught that until now, but I fixed my answer. –  Sep 18 '12 at 15:56
  • @crazy2be: Speak for yourself. CppCheck currently warns against this kind of errors and saved my neck a couple times. If you mean assignment, it suggests extra pair of parentheses, if((q=!p)) goes without warning. – SF. Jan 09 '13 at 13:13
  • Actually it does look more readable, if the dynamic part of the condition is significantly longer than the static part. if (false !== strpos(ucfirst('the fox jumped over the hedge'), 'fox') {..} This allows to immediately see the toplevel comparison operator. The length of the dynamic part could be due to long variable names, or to expressions. – donquixote Feb 11 '16 at 07:51
  • It can also increase readability in some kind of switch implemented as if/else. if ('red' === $color) {..} elseif ('blue' === $color) {..} elseif ('green' === $color) {..} else {..}. Here the string literals have the higher information value for a reader. – donquixote Feb 11 '16 at 07:53
  • Japanese people read many things in reverse, so the "Yoda condition" might be more readable to them. Besides I've read in some rationale that putting the const first makes it more easily to find the correct branch in a series of if () else if () else if ()... – phuclv Jan 24 '20 at 23:53
14

It's a defensive coding mechanism meant to prevent an accidental use of the assignment operator.

Consider a misuse/error of the assignment operator in place of the equality operator

if ( $options['postlink'] = 1  )

The above conditional would always return true, but that's probably not what the original programmer had in mind. Consider, in it's place, this

if( 1 = $options['postlink'])

Here, PHP (and most other languages) would refuse to run, as it's impossible to assign anything to the fixed value of 1. By coding up all the conditional statements this way, you automatically ensure no accidental usage of an assignment operator in a conditional.

Alana Storm
  • 301
  • 1
  • 7
10

I like using that convention in java to remove the possibility of a null pointer exception. So something like this won't cause you any problems or need any extra code:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
1

In practice, many compilers will give you a warning if you write "if (x = 1)" instead of "if (x == 1)" because it is most likely a mistake.

With Clang, you can avoid the warning by effectively telling the compiler "I mean it, and I know what I'm doing", and this is done by writing "if ((x = 1))". Note the extra parentheses. That works in other situations as well. if (false) statement; may give you a warning that the statement is never executed; if ((false)) statement; doesn't give that warning.

PS. Many languages nowadays require that the expression in an "if" statement is boolean, without any automatic conversion. In "if (x = 1)" the expression has type "int" so it won't be accepted, except for the rare case "if (bool1 = bool2)".

gnasher729
  • 44,814
  • 4
  • 64
  • 126
  • I like that a lot! I avoid the following, completely legit idiom in PHP because I always get warnings in my IDE: if ($array = getSomething()){ // ..so something with $array } – Tom Auger May 22 '19 at 13:57
-1

if ($variable == 'constant')

Because you spend more time reading code than writing it (see https://www.goodreads.com/quotes/835238-indeed-the-ratio-of-time-spent-reading-versus-writing-is), and this form is easier to read.

Although User8 has a valid argument to have the constant first; that's reasoning about what to do from the code writer's perspective. Normally, there are less experienced coders reading code, and they need all the help they can get in matching the natural order that would have the constant laste. (And of course, good language design and compiler checks overcome the stated problem).

  • good language design and compiler checks overcome the stated problem Except when they don't. The entire purpose of Yoda conditions is to act as just one tool to *prevent* the creation of bugs, not merely hope they are discovered by something before causing problems. – Andrew Henle Mar 17 '21 at 10:30
  • @AndrewHenle That was in brackets, because that isn't my answer, but food for thought. Different people have different circumstances and are quite free to apply accordingly. – Kind Contributor Mar 18 '21 at 00:04
  • -1 for: reviving a very old question, adding nothing new to the pool of knowledge, and generally coming across as arrogant and superior. That's not really the culture here. You can do better. – Tom Auger Mar 26 '21 at 17:58
  • @TomAuger I'm a humble answerer, with no world-domination ambitions. Kindly point out which section of my answer is at fault and I will endeavor to improve it for the community. – Kind Contributor Apr 04 '21 at 12:09