Interesting little trick I picked up a while back, been meaning to blog about it. If you're already in the loop, run along.
Prior to enlightenment, I used to write conditionals something like this:
[php]if ($var == SOME_CONSTANT_CONDITION) { // do something } [/php]
... more specifically:
[php]if ($var == TRUE) { // do the true thing } [/php]
That's how I'd "say" it, so that's how I wrote it. But is it the best way? I now don't think so. When reviewing other peoples' code (often from C programmers), I've seen "backwards" conditionals.. something like:
[php]if (TRUE == $var) { // ... } [/php]
Which just sounds weird. Why would you compare a constant to a variable (you'd normally compare a variable to a constant).
So, what's the big deal?
Well, a few months back, I stumbled on an old article about a backdoor almost sneaking into Linux.
Here's the almost-break:
[code]if ((options == (__WCLONE|__WALL)) && (current->uid = 0)) retval = -EINVAL; [/code]
Ignore the constants, I don't know what they mean either. The interesting
part is current->uid = 0
See, unless you had your eyes peeled, here, it might look like you're trying to ensure that current->uid is equal to 0 (uid 0 = root on Linux). So, if options blah blah, AND the user is root, then do something.
But wait. There's only a single equals sign. The comparison is "==". "=" is for assignment!
Fortunately, someone with good eyes noticed, and Linux is safe (if this had made it into a release, it would've been trivial to escalate your privileges to the root level).. but how many times have you had this happen to you? I'm guilty of accidentally using "=" when I mean "==". And it's hard to track down this bug.. it doesn't LOOK wrong, and the syntax is right, so...
This is nothing new. Everyone knows the = vs == problem. Everyone is over it (most of the time). But how can we reduce this problem?
A simple coding style adjustment can help enormously here.
Consider changing "$var == TRUE" to "TRUE == $var".
Why? Simple:
[code]sean@iconoclast:~$ php -r '$a = 0; if (FALSE = $a) $b = TRUE;' Parse error: parse error in Command line code on line 1[/code]
Of course, you can't ASSIGN $a to the constant FALSE. The same style applied above would've caused a a similar error in the C linux kernel code:
[code]if ((options == (__WCLONE|__WALL)) && (0 = current->uid ))[/code]
Obviously, "0" is a constant value--you cannot assign a value to it. The missing "=" would've popped up right away.
Cool. Seems a little awkward at first, but in practice, it make sense.
HTH.
I understand the possible arguments for if(FALSE == $myvar), but I don't like it.
The subject you are interested in should come first, as in proper language (spoken, even). Asking if false is the same as some variable is masking the fact that the variable is what we're interested in.
It reminds me of the movie "Way of the Gun" when a guy is at a sperm donor bank to donate for cash and in the interview, the interviewer is filling out his vital stats form and asks "Heterosexual?". Of course, it makes more sense for the interviewer to ask if he is homosexual, because that's *really* what he is trying to find out, however he's dancing around it.
Did you follow the zend exam ? because this example is also in the study book :)
I agree with hermit. Code should be close to the human language (one of the reasons why I haven't started with Ruby yet, the syntax is not my cup of tea).
Changing your syntax to avoid semantical bugs? Some decent unit tests (and we are probably all guilty of writing too few ;-) should be the answer, or am I mistaken?
I've been using this for quite some time now and it saved me lot of troubles. So I absolutely agree that it's useful. It may seem a little bit awkward at first, but since it's not really obscure, I'd say it's fine.
I have been doing this for a few years. It is absolutely the best way to do things. A real time saver.
In most of my code, I'm comparing stuff to other stuff. There's only a portion that's compared with constants. I find the decreased chance of assignment errors not worth the decreased readability of the code.
I suspect that in more complex comparisons, the chances of making mistakes in 'backwards' code is higher than the chance of a regular assignment error.
Also, aren't there IDE's out there that warn for this type of mistake?
Seems like an excellent idea to me. Thank you.
Balony! Code is written to be read by coders, and to be compiled/interpreted only by computers. I would appreciate if there was some sort of precompiler that would just swap them around before running the code. But this is awful.
To prevent this type of error, and lots of others, start using assert(). That's easier to come up with then a unit test case, and if done properly does the very same thing, only at run time. Chances are very very small that you'd make the same mistake in the assert again.
Lots of people recommend doing the checking variables that way so that you don't accidently do variable assignment during if checking. It's a mission to change coding style ;)
Maybe Pascal's usage of ":=" as assignment operator isn't that out of place after all. I agree that code should be as readable as possible, hence the variable should come first...
Maybe a compiler notice for "possible non-intended assignement in boolean evaluation" if an assignment takes place within an if() clause...? Althought that would also highlight things like:
if (!$result = $database->query($sql))
But since it would be just a notice...
I've been doing a lot of looking around at PHP stuff recently, as well as doing a bunch of PHP coding -- something I'd dropped doing a while ago.
First, I found some interesting stats about PHP's use, citing PHP's use at 22,172,983 Domains, and 1,277,
Yeah, I think Pascal got it right, assignment is simply not the same as equivalence, and the := operator reflects that. As to the reverse comparisons, it's in the C FAQ somewhere.
On occasion I have toyed with that syntax, but yes, it runs contrary to literate programming. In the end I decided to try to write readable code, and not funky / overly clever code.
Why you can't code like this:
if ($var) {
...
}
?