I am told that good developers can spot/utilize the difference between Null and False and 0 and all the other good "nothing" entities.
What is the difference, specifically in PHP? Does it have something to do with ===?
views:
3894answers:
14The differences between these values always come down to detailed language-specific rules. What you learn for PHP isn't necessarily true for Python, or Perl, or C, etc. While it is valuable to learn the rules for the language(s) you're working with, relying on them too much is asking for trouble. The trouble comes when the next programmer needs to maintain your code and you've used some construct that takes advantage of some little detail of Null vs. False (for example). Your code should look correct (and conversely, wrong code should look wrong).
Null is nothing, False is a bit, and 0 is (probably) 32 bits.
Not a PHP expert, but in some of the more modern languages those aren't interchangeable. I kind of miss having 0 and false be interchangeable, but with boolean being an actual type you can have methods and objects associated with it so that's just a tradeoff. Null is null though, the absence of anything essentially.
False, Null, Nothing, 0, Undefined, etc., etc.
Each of these has specific meanings that correlate with actual concepts. Sometimes multiple meanings are overloaded into a single keyword or value.
In C and C++, NULL, False and 0 are overloaded to the same value. In C# they're 3 distinct concepts.
null or NULL usually indicates a lack of value, but usually doesn't specify why. 0 indicates the natural number zero and has type-equivalence to 1, 2, 3, etc. and in languages that support separate concepts of NULL should be treated only a number.
False indicates non-truth. And it used in binary values. It doesn't mean unset, nor does it mean 0. It simply indicates one of two binary values.
Nothing can indicate that the value is specifically set to be nothing which indicates the same thing as null, but with intent.
Undefined in some languages indicates that the value has yet to be set because no code has specified an actual value.
Null is used in databases to represent "no record" or "no information". So you might have a bit field that describes "does this user want to be sent e-mails by us", where True means they do, False means they don't want to be sent anything, but Null would mean that you don't know. They can come about through outer joins and suchlike.
The logical implications of Null are often different - in some languages NULL is not equal to anything, so if(a == NULL) will always be false.
So personally I'd always initialise a boolean to FALSE, and initialising one to NULL would look a bit icky (even in C where the two are both just 0... just a style thing).
Well, I can't remember enough from my PHP days to answer the "===" part, but for most C-style languages, NULL should be used in the context of pointer values, false as a boolean, and zero as a numeric value such as an int. '\0' is the customary value for a character context. I usually also prefer to use 0.0 for floats and doubles.
So.. the quick answer is: context.
In PHP it depends on if you are validating types:
( ( false !== 0 ) && ( false !== -1 ) && ( false == 0 ) && ( false == -1 ) && ( false !== null ) && ( false == null ) )
Technically null is 0x00 but in PHP ( null == 0x00 ) && ( null !== 0x00 ).
0 is an integer value.
I think bad developers find all different uses of null/0/false in there code.
For example, one of the most common mistakes developers make is to return error code in the form of data with a function.
// On error GetChar returns -1
int GetChar()
This is an example of a sugar interface. This is exsplained in the book "Debuging the software development proccess" and also in another book "writing correct code".
The problem with this, is the implication or assumptions made on the char type. On some compilers the char type can be non-signed. So even though you return a -1 the compiler can return 1 instead. These kind of compiler assumptions in C++ or C are hard to spot.
Instead, the best way is not to mix error code with your data. So the following function.
char GetChar
now becomes
// On success return 1
// on failure return 0
bool GetChar(int &char)
This means no matter how young the developer is in your development shop, he or she will never get this wrong. Though this is not talking about redudancy or dependies in code.
So in general, swapping bool as the first class type in the language is okay and i think joel spoke about it with his recent postcast. But try not to use mix and match bools with your data in your routines and you should be perfectly fine.
In pretty much all modern languages, null logically refers to pointers (or references) not having a value, or a variable that is not initialized. 0 is the integer value of zero, and false is the boolean value of, well, false. To make things complicated, in C, for example, null, 0, and false are all represented the exact same way. I don't know how it works in PHP.
Then, to complicate things more, databases have a concept of null, which means missing or not applicable, and most languages don't have a direct way to map a DBNull to their null. Until recently, for example, there was no distinction between an int being null and being zero, but that was changed with nullable ints.
Sorry to make this sound complicated. It's just that this has been a harry sticking point in languages for years, and up until recently, it hasn't had any clear resolution anywhere. People used to just kludge things together or make blank or 0 represent nulls in the database, which doesn't always work too well.
From the PHP online documentation:
"*To explicitly convert a value to boolean, use the (bool) or (boolean) casts. However, in most cases the cast is unncecessary, since a value will be automatically converted if an operator, function or control structure requires a boolean argument. When converting to boolean, the following values are considered FALSE: * the boolean FALSE itself * the integer 0 (zero) * the float 0.0 (zero) * the empty string, and the string "0" * an array with zero elements * an object with zero member variables (PHP 4 only) * the special type NULL (including unset variables) * SimpleXML objects created from empty tags Every other value is considered TRUE (including any resource).* "
So, in most cases, it's the same.
On the other hand, the "===" and the "==" are not the same thing. Regularly, you just need the "equals" operator. To clarify:
$a == $b //Equal. TRUE if $a is equal to $b.
$a === $b //Identical. TRUE if $a is equal to $b, and they are of the same type.
For more information, check the "Comparison Operators" page in the PHP online docs.
Hope this helps.
One interesting fact about NULL in PHP: If you set a var equal to NULL, it is the same as if you had called unset() on it.
NULL essentially means a variable has no value assigned to it; false is a valid Boolean value, 0 is a valid integer value, and PHP has some fairly ugly conversion between 0, "0", "", and false.
False and 0 are conceptually similar, i.e. they are isomorphic. 0 is the initial value for the algebra of natural numbers, and False is the initial value for the Boolean algebra.
In other words, 0 can be defined as the number which, when added to some natural number, yields that same number:
x + 0 = x
Similarly, False is a value such that a disjunction of it and any other value is that same value:
x || False = x
Null is conceptually something totally different. Depending on the language, there are different semantics for it, but none of them describe an "initial value" as False and 0 are. There is no algebra for Null. It pertains to variables, usually to denote that the variable has no specific value in the current context. In most languages, there are no operations defined on Null, and it's an error to use Null as an operand. In some languages, there is a special value called "bottom" rather than "null", which is a placeholder for the value of a computation that does not terminate.
I've written more extensively about the implications of NULL elsewhere.
In PHP you can use === and !== operators to check not only if the values are equal but also if their types match. So for example: 0 == false
is true
, but 0 === false
is false
. The same goes for !=
versus !==
. Also in case you compare null
to the other two using the mentioned operators, expect similar results.
Now in PHP this quality of values is usually used when returning a value which sometimes can be 0
(zero), but sometimes it might be that the function failed. In such cases in PHP you return false
and you have to check for these cases using the identity operator ===
. For example if you are searching for a position of one string inside the other and you're using strpos()
, this function will return the numeric position which can be 0 if the string is found at the very beginning, but if the string is not found at all, then strpos()
will return false
and you have to take this into account when dealing with the result.
If you will use the same technique in your functions, anybody familiar with the standard PHP library will understand what is going on and how to check if the returned value is what is wanted or did some error occur while processing. The same actually goes for function params, you can process them differently depending on if they are arrays or strings or what not, and this technique is used throughout PHP heavily too, so everybody will get it quite easily. So I guess that's the power.
It's language specific, but in PHP :
"Null" means "nothing". The var has not been initialized.
"False" means "not true in a boolean context". Used to explicitely show you are dealing with logical issues.
0 is an int. Nothing to do with the rest above, used for mathematics.
Now, what is tricky, it's that in dynamic languages like PHP, all of them have a value in a boolean context, which is "False".
If you test it with "==", it's testing the boolean value, so you will get equality. If you test it with "===", it will test the type, and you will get inequality.
So why are they useful ?
Well, look at the strrpos() function. It returns False if it did not found anything, but 0 if it has found something at the begining of the string !
<?php
// pitfall :
if (strrpos("Hello World", "Hello")) {
// never exectuted
}
// smart move :
if (strrpos("Hello World", "Hello") !== False) {
// that works !
}
?>
And of course, if you deal with states :
You want to make a difference between DebugMode = False (set to off), DebugMode = True (set to on) and DebugMode = Null (not set at all, will lead to hard debugging ;-)).
In general, programming languages tend to have truthy and falsy values. The rules for what is truthy and what is falsy vary from language to language.
http://www.isolani.co.uk/blog/javascript/TruthyFalsyAndTypeCasting