Why =! seems a legit condition in php? - php

I just experienced a sort of bug while coding in Php:
I was writing some condition like this:
if($showPrice != 0){
$worksheet->mergeCells('A'.$rowCount.':F'.$rowCount);
$worksheet->SetCellValue('A'.$rowCount, 'Total Weight');
$worksheet->SetCellValue('G'.$rowCount, $totalWeight);
}else{
$worksheet->mergeCells('A'.$rowCount.':D'.$rowCount);
$worksheet->SetCellValue('A'.$rowCount, 'Total Weight');
$worksheet->SetCellValue('E'.$rowCount, $totalWeight);
}
I noticed that instead of writing != as I should, I was wrongly writing =! without getting any error.
What could be the reason of this?

You didn't find any bug in PHP. You found a bug in your program and in your knowledge about the PHP.
$x =! 0 is, in fact, $x = !0.
! is the logical NOT operator.
0 is evaluated as FALSE in boolean context, consequently !0 is TRUE.
$x = ... is a regular assignment. As any assignment, it does two things:
stores the value of the right-hand side expression into the left-hand side variable; here the expression is !0 that, as explained above, is evaluated to TRUE;
the value of the entire expression ($x = !0) is the value of $x after the assignment (TRUE as described).
When the assignment it is used as a statement, its value is discarded. When it is used as a condition (in a for, while, if, switch statement), its value is used to control the execution of the code.
Here, if($showPrice =! 0) always takes the if branch (and never the else branch) because the value of the $showPrice = !0 expression is always TRUE as explained above.
More, the value of $showPrice also becomes TRUE after this statement is evaluated.
Two bugs in a single line of code.
From the PHP's point of view the code is perfectly valid and, even if it is unusual, maybe it represents the programmer's intention. The interpreter doesn't have any reason to complain about it. It can be, however, detected and flagged as a possible error by static code analysis tools and some PHP IDEs.

Related

Assignment statement with AND operator

Can any one explain me following construct.
I do googling for this about 2 hours but can't understand.
public function __construct($load_complex = true)
{
$load_complex and $this->complex = $this->getComplex();
}
See: http://www.php.net/manual/en/language.operators.logical.php
PHP uses intelligent expression evaluation. If any of AND's operands evaluates to false, then there is no reason to evaluate other, because result will be false.
So if $load_complex is false there is no need to evaluate $this->complex = $this->getComplex();
This is some kind of workaround, but I do not suggest to use it, because it makes your code hard to read.
Specifically to your example $this->complex = $this->getComplex() if and only if $load_complex is set to true.
LIVE DEMO
NOTE: If any one of OPERAND result becomes 'false' in short
circuit AND evaluation means, the part of statement will be
OMITTED because there is no need to evaluate it.
Dont code like below line because, you may get probably logical
error while you are putting Expression instead of assigning values
to the variable on LEFT HAND SIDE...
$load_complex and $this->complex = $this->getComplex();
I have modified below with conditinal statement for your needs...
if($load_complex and $this->complex) {
$this->getComplex();
}

Processing of php 'if x && y'

I was wondering how php processes if statements.
If i were to have something such as:
if (isset($_GET['foo']) && $_GET['foo'] != $bar)
If foo isn't set, would it then drop out of the if straight away (as it is an 'and' statement so it can't succeed anyway) or would it also check the second part, rather pointlessly?
What you're describing is known as "short-circuit evaluation".
Most languages work this way, including PHP, so they will evaluate an expression until they are certain of the result, and then stop, so the remainder of the expression would not be evaluated.
As you say, this is the most efficient approach.
However, it can potentially throw a spanner in the works for inexperienced programmers, who nay try something like this:
if(doFirstProcess() && doSecondProcess() {
print "both processes succeeded";
}
In this case, the programmer is expecting both functions to be called, but if the first one returns false, then the second one will not be executed, as the program already knows enough to be certain of the final result of the expression, so it short-circuits the remainder of the expression.
There are a few languages which don't do short-circuit evaluation. VB6 was one example (back in the day). I don't know about VB.Net, but since it's evolved from VB6, I would suspect it would be similar. But aside from that, all other languages that I've worked with have used short-circuit evaluation, including PHP.
There is a section in the PHP manual about this here: http://www.php.net/manual/en/language.operators.logical.php
And you can read more on short circuit evalution here: http://en.wikipedia.org/wiki/Short-circuit_evaluation
Hope that helps.
It's known as short-circuit:
&& and and operators is executed from left to side
If left side is considered false, no reasons to check right side, so it's omitted, false returned
|| and or operators is executed from left to side too
If left side is considered true, no reasons to check right side, so it's omitted, true returned
Manual example:
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
it will leave the if statement after the first expression evaluates to false because this statement can never be true if the first one is false and they are combinded via AND
you can check this very easily. If it wouldn't be like I said, you would get a notice that $_GET['foo'] is not defined
If the first part is false, it stops the if.
Certain operators, most notably && and || are so-called short-circuit operators, meaning that if the result of the operation is clear from the first operand (false or true, respectively), the second operand does not get evaluated.
Edit: Additionally, operands are guaranteed to be evaluated in order, this is not always true of other operators.
Will go out after the first statement.
you can test it:
will print 1:
if(1==1 && $a=1 == 1){
}
print $a;
Will not print a thing:
if(1==2 && $a=1 == 1){
}
print $a;
&& does short-circuit (i.e. returns false as soon as one condition fails).
If it doesn't, then having the isset would be pointless — it exists to prevent errors when trying to compare an undefined value to a string.
If the first check if (isset($_GET['foo']) returns false, the second part will not even be looked into anymore.

Question with setting variables in if statements

Here is the sample:
if(($test = array('key'=>true)) && $test['key']){
// works
}
if($test = array('key'=>true) && $test['key']){
// does not work
}
Why is the parenthesis required? My understanding is that it computes the first conditional then the second no matter what.
And is it "safe" to do an assignment like this?
It's a matter of operator precedence in the language. In your second statement, you're essentially writing this to be evaluated:
$test = array('key'=>true) && $test['key'];
Just about any language is going to take that to mean this:
$test = (array('key'=>true) && $test['key']);
It's assigning to $test the value of the evaluation of the logical && between the two other values. So $test will be either true or false when evaluated.
i don't think the parens are required in PHP. they are in JS.
depends what you mean by "safe". it works. but some would argue that this is bad style and makes for less understandable and less maintainable code. otoh, K&R positively recommended it. it doesn't worry me and sometimes makes for tidier code.
It's because it's forcing the interpreter to perform the assignment before it attempts to evaluate any of conditions within the if.
Without the parenthesis, you're simply assigning the results of array('key'=>true) && $test['key'] to $test.
It is safe to use, but in this case the parenthesis are required for disambiguation. The operator precedence rules of PHP mean that the second line will be executed as:
if ($test = (array('key' => true) && $test['key'])) { .. }
So test will not be an array but a bool.
The practice of doing assignment in if statements itself is not really encouraging readability though, so you probably want to avoid doing this too much.
In PHP, the assignment operator = has lower precedence that most other operators. (For more information, see the documentation). Furthermore, the result of an expression using the assignment operator is the value of the assignment. With this in mind, consider the expressions you posted:
First example:
($test = array('key'=>true)) && $test['key']
The first part of this expression, ($test = array('key'=>true)) evaluates to array('key'=>true) (by the rule above), and the second part evaluates to true since the key was just set. Thus the whole expression evaluates to true.
Second example:
$test = array('key'=>true) && $test['key'] By the rules of operator precedence, $test is going to get assigned the value of the expression array('key'=>true) && $test['key']. The first half of this is true, but $test['key'] hasn't been set yet, so true && false is false, so $test takes the value false, which is also the result of the if condition.

Strange variable assignment

I was studying some code I found on the web recently, and came across this php syntax:
<?php $framecharset && $frame['charset'] = $framecharset; ?>
Can someone explain what is going on in this line of code?
What variable(s) are being assigned what value(s), and what is the purpose of the && operator, in that location of the statement?
Thanks!
Pat
Ah, I just wrote a blog post about this idiom in javascript:
http://www.mcphersonindustries.com/
Basically it's testing to see that $framecharset exists, and then tries to assign it to $frame['charset'] if it is non-null.
The way it works is that interpreters are lazy. Both sides of an && statement need to be true to continue. When it encounters a false value followed by &&, it stops. It doesn't continue evaluating (so in this case the assignment won't occur if $framecharset is false or null).
Some people will even put the more "expensive" half of a boolean expression after the &&, so that if the first condition isn't true, then the expensive bit won't ever be processed. It's arguable how much this actually might save, but it uses the same principle.
&& in PHP is short-circuited, which means the RHS will not be evaluated if the LHS evaluates to be false, because the result will always be false.
Your code:
$framecharset && $frame['charset'] = $framecharset;
is equivalent to :
if($framecharset) {
$frame['charset'] = $framecharset;
}
Which assigns the value of $framecharset as value to the array key charset only if the value evaluates to be true and in PHP
All strings are true except for two: a string containing nothing at all and a string containing only the character 0

if statement condition optimisation

I have an if statement with two conditions (separated by an OR operator), one of the conditions covers +70% of situations and takes far less time to process/execute than the second condition, so in the interests of speed I only want the second condition to be processed if the first condition evaluates to false.
if I order the conditions so that the first condition (the quicker one) appears in the if statement first - on the occasions where this condition is met and evaluates true is the second condition even processed?
if ( (condition1) | (condition2) ){
// do this
}
or would I need to nest two if statements to only check the second condition if the first evaluates to false?
if (condition1){
// do this
}else if (condition2){
// do this
}
I am working in PHP, however, I assume that this may be language-agnostic.
For C, C++, C#, Java and other .NET languages boolean expressions are optimised so that as soon as enough is known nothing else is evaluated.
An old trick for doing obfuscated code was to use this to create if statements, such as:
a || b();
if "a" is true, "b()" would never be evaluated, so we can rewrite it into:
if(!a)
b();
and similarly:
a && b();
would become
if(a)
b();
Please note that this is only valid for the || and && operator. The two operators | and & is bitwise or, and and, respectively, and are therefore not "optimised".
EDIT:
As mentioned by others, trying to optimise code using short circuit logic is very rarely well spent time.
First go for clarity, both because it is easier to read and understand. Also, if you try to be too clever a simple reordering of the terms could lead to wildly different behaviour without any apparent reason.
Second, go for optimisation, but only after timing and profiling. Way too many developer do premature optimisation without profiling. Most of the time it's completely useless.
Pretty much every language does a short circuit evaluation. Meaning the second condition is only evaluated if it's aboslutely necessary to. For this to work, most languages use the double pipe, ||, not the single one, |.
See http://en.wikipedia.org/wiki/Short-circuit_evaluation
In C, C++ and Java, the statement:
if (condition1 | condition2) {
...
}
will evaluate both conditions every time and only be true if the entire expression is true.
The statement:
if (condition1 || condition2) {
...
}
will evaluate condition2 only if condition1 is false. The difference is significant if condition2 is a function or another expression with a side-effect.
There is, however, no difference between the || case and the if/else case.
I've seen a lot of these types of questions lately--optimization to the nth degree.
I think it makes sense in certain circumstances:
Computing condition 2 is not a constant time operation
You are asking strictly for educational purposes--you want to know how the language works, not to save 3us.
In other cases, worrying about the "fastest" way to iterate or check a conditional is silly. Instead of writing tests which require millions of trials to see any recordable (but insignificant) difference, focus on clarity.
When someone else (could be you!) picks up this code in a month or a year, what's going to be most important is clarity.
In this case, your first example is shorter, clearer and doesn't require you to repeat yourself.
According to this article PHP does short circuit evaluation, which means that if the first condition is met the second is not even evaluated.
It's quite easy to test also (from the article):
<?php
/* ch06ex07 – shows no output because of short circuit evaluation */
if (true || $intVal = 5) // short circuits after true
{
echo $intVal; // will be empty because the assignment never took place
}
?>
The short-circuiting is not for optimization. It's main purpose is to avoid calling code that will not work, yet result in a readable test. Example:
if (i < array.size() && array[i]==foo) ...
Note that array[i] may very well get an access violation if i is out of range and crash the program. Thus this program is certainly depending on short-circuiting the evaluation!
I believe this is the reason for writing expressions this way far more often than optimization concerns.
While using short-circuiting for the purposes of optimization is often overkill, there are certainly other compelling reasons to use it. One such example (in C++) is the following:
if( pObj != NULL && *pObj == "username" ) {
// Do something...
}
Here, short-circuiting is being relied upon to ensure that pObj has been allocated prior to dereferencing it. This is far more concise than having nested if statements.
Since this is tagged language agnostic I'll chime in. For Perl at least, the first option is sufficient, I'm not familiar with PHP. It evaluates left to right and drops out as soon as the condition is met.
In most languages with decent optimization the former will work just fine.
The | is a bitwise operator in PHP. It does not mean $a OR $b, exactly. You'll want to use the double-pipe. And yes, as mentioned, PHP does short-circuit evaluation. In similar fashion, if the first condition of an && clause evaluates to false, PHP does not evaluate the rest of the clause, either.
VB.net has two wonderful expression called "OrElse" and "AndAlso"
OrElse will short circuit itself the first time it reaches a True evaluation and execute the code you desire.
If FirstName = "Luke" OrElse FirstName = "Darth" Then
Console.Writeline "Greetings Exalted One!"
End If
AndAlso will short circuit itself the first time it a False evaluation and not evaluate the code within the block.
If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
Console.Writeline "You are the one and only."
End If
I find both of these helpful.

Categories