note 30352 deleted from language.operators.logical by colder
| From: | colder@php.net | Date: | Fri, 20 Apr 2007 15:38:53 +0000 |
| Subject: | note 30352 deleted from language.operators.logical by colder | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-125696@lists.php.net to get a copy of this message | ||
Note Submitter: shadedecho
----
It appears (after much frustrating but ultimately helpful searching and discussion on forums like
tek-tips) that the
|| and the && are "short-circuited" as has been previously noted BUT the | and
& operators (documented by PHP as bitwise operators) behave as their non-short-circuited
counter-parts, respectively.
ex:
function blah() {
echo "hello< br>";
return "from blah()< br>";
}
function blah2() {
echo "world\< br>";
return "from blah2()< br>";
}
$a = "";
if ( ($a .= blah()) || ($a .= blah2()) ) {
echo $a;
}
This would result in the following output:
hello
from blah()
Notice the "world" didn't get echo'd and the "from blah2()"
didn't get concat'd into the $a variable, because the first assigment to $a was
successful, so the "short-circuting" kicks in and the boolean test terminates without
evaluating the rest of it.
HOWEVER, if you replace || with just | in that "if" statement, you get the output:
hello
world
from blah()
from blah2()
Eureka! all parts of the boolean test are evaluated, in expected left-to-right fashion, and
following all the normal precendence rules, so far as I can see.
This makes total sense... Using the bitwise operators, what is occurring is the bitwise-level
operation on the result of two non-bitwise operations (the assignments). If a non-bitwise operation
returns null (in other words, the value being assigned turns out to be null or 0), the bitwise
operator would bind to that (or more appropriately, would "see" it) as a "0",
otherwise it would see a non-zero (string of bits with at least one "1" in it).
Then a bitwise | is done on the two values, and if either is non-zero (has "1" bits in it)
then the result will have those "1" bits in it (non-zero), and the if statement will
interpret any non-zero value as true in a boolean test. Likewise, if both operands to the | were
null or 0, then the result would be a zero value, which "if" would interpret as false.
The if statement above is doing a bitwise | on (in this case) two non-zero values (with
"1"s in it at the bit level), so the | operation returns a non-zero value which is then
reinterpreted by the if statement as TRUE!
So, in this special case where you are trying to string together non-short-circuited boolean tests,
these operators work on their operands at the bitwise level, and since they are not comparison
operators but mathematical operators, they can't be short-circuited, and the resulting behavior
is a non-short-circuited "boolean test".
I know, you must think I am crazy for trying to get around a built-in optimization like this, but I
assure you there is a very good reason for it, and if you are interested, you can check out this
thread as I have a very long post in there which explains what I was trying to do:
It is the 9th post down, where you will find my description of my database query'ing which i
was wanting to optimize.
http://www.tek-tips.com/gviewthread.cfm/lev2
/4/lev3/31/pid/434/qid/500825
(note i had to split that URL for the post, but it should be all together on one line obviously)