Is =! a declaration and is that why this alternating conditional works? - php

I have a terrible confession. I've been using variations of the below for ages.
for($x=0;10>$x;++$x){
echo '<li style="color:#'.(($c=!$c)? "fff":"eee").'">example $x</li>";
}
My dilemma is that I don't entirely understand how it works. I know that $c=!$c makes the ternary conditional alternate, but I don't understand how. Googling "php =!" and the likes yields nothing helpful (no surprise given the query).
!= is an operator, but this uses =!
Is this a ternary conditional declaration? If so, how does this one work? I understand the general conditional declarations, but not this one... assuming it even is one.
Any answer or link to documentation would be greatly appreciated.

They are two separate operators. You should read it as
$c = !$c;
In other words, assign the result of the expression !$c back to the variable $c. So indeed, it toggles the value of $c.
Additionally, an assignment like this also returns the assigned value, so you can evaluate it immediately. So in words, the expression ($c=!$c)? "fff":"eee" says:
"Invert the value of $c. If the new value is true, return 'fff', otherwise return 'eee'."

It's not an operator, it just needs better spacing:
$x = !$x;
it's just inverting the value.

=! is not an operator. It is two: = means assignment, and ! means negation.
If $c is true, then !$c is false (and vice versa).
And assignments evaluate to their new value.

You're setting $c to be not itself. So if $c == true you are saying $c = not true, I.e. false which will also count as false for the ternary.
Next iteration you set $c = not false I.e. true and so on.

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.

Can someone explain this line of code please? (Logic & Assignment operators)

I've seen the following lines of code and I know what they do, but I don't know how the second line works (and hence how to apply it to another situation).
$user = User::model()->findByPk(123);
empty($user->profile) and $user->profile = new Profile();
The code tries to look up the User from the database, and if there isn't a profile, creates a new for use later on.
I have also seen code before that goes something like the following:
$variable1 = $variable2 = $variable3;
It did something a bit more complex than simple assigning three things to be the same, but I'm finding it impossible to search for this type of thing to find out any information about it, let alone find the original code that I came across. I think it originally had an 'and' in there somewhere. Does anyone know how to search for code that has more than one equals sign in it that wasn't just an if statement?
Sorry for the two questions in one (and vague at that) and the terrible title (I'll fix it up when I know what the names are, if it's anything like a tenary statement)).
Using Logical Operators to Skip Code:
As php evaluates a line with the AND operator, if the fist part is false, the second part is not evaluated since it would not change the result.
So in this case, if empty() returns true, then php evaluates the right side. If empty() returns false, no more evaluation is done and the profile is not effected.
The php manual logical operators page has some illustrations of this.
Multiple Assignment Operators: The assignment operator assigns the right expression to the variable on the left.
$variable1 = $variable2 = $variable3;
In this case $variable2 is set to the value of $variable3 then $variable1 is set to the value of $variable2. The php manual assignment operators page covers this.
empty($user->profile) and $user->profile = new Profile();
in and statement, first element is evaluated first; if it's true, then second statement is evaluated, simple assignment should always evaluate to true, I presume. if the first element was false, second element is not evaluated.
You can read more about operator precedence in php docs.
It's basically the same as
if (empty($user->profile))
$user->profile = new Profile();
Weird syntax indeed...
What you're seeing is used in many languages. Here is an article for using it in JavaScript... but it explains the concept well.
http://css.dzone.com/articles/guard-and-default-operators-ja
This is a fairly bizarre way to write this. With a PHP expression, if the first part evaluates false, the expression will stop rendering.
Like if I write:
if (x == 5 and y == 2)
that will test if x==5, then if it does, it will test if y==2. If x != 5, it will never test the y == 2. So the code above is using that fact to test whether $user->profile is empty. Then if it is, it runs the next part of the expression, which is the assignment of $user->profile = new Profile(); Basically the same as:
if (empty($user->profile))
$user->profile = new Profile();
or
empty($user->profile) ? $user->profile = new Profile();
As far as your second question, the operator = is just an assignment, so it means that the value of $variable1 will be set to the value of $variable2, which will be set to the value of $variable3.
PHP does some very nice things with expressions, which are really helpful to learn. Check out this link for more info:
http://us.php.net/manual/en/language.expressions.php
$variable1 = $variable2 = $variable3;
Assignment (via the equal sign) in PHP has right to left precedence. Every expression in PHP has a return value. So the return value of the expression $variable3 is assigned to $variable2. Then the reurn value of the expression $variable2 = $variable3 is assigned to $variable1.

How can I have PHP avoid lazy evaluation?

I have an interesting question about the way PHP evaluates boolean expressions. When you have, for example,
$expression = $expression1 and $expression2;
or
if ($expression1 and $expression2)
PHP first checks if $expression1 evaluates to true. If this is not the case, then $expression2 is simply skipped to avoid unnecessary calculations. In a script I am writing, I have:
if ($validator->valid("title") and $validator->valid("text"))
I need to have the second statement ($validator->valid("text")) evaluated even if the first one evaluates to false. I would like to ask you whether there is some easy way to force PHP to always evaluate both statements. Thank you!
$isValidTitle = $validator->valid("title");
$isValidText = $validator->valid("text");
if($isValidTitle && $isValidText)
{
...
}
Will that suit?
This is known as short circuit evaluation, and to avoid it you need to do this, using a single &:
if($validator->valid("title") & $validator->valid("text")) {
}
Note that this is not using logical operators but actually bitwise operators:
They're operators that act on the binary representations of numbers. They do not take logical values (i.e., "true" or "false") as arguments without first converting them to the numbers 1 and 0 respectively. Nor do they return logical values, but numbers. Sure, you can later treat those numbers as though they were logical values (in which case 0 is cast to "false" and anything else is cast to "true"), but that's a consequence of PHP's type casting rules, and nothing to do with the behavior of the operators.
As such, there is some debate as to whether it is good practice to use this side effect to circumvent short-circuit evaluation. I would personally at least put a comment that the & is intentional, but if you want to be as pure as possible you should evaluate whether they are valid first and then do the if.
try to evaluate each term separately:
$term1 = $validator->valid("title");
$term2 = $validator->valid("text");
if($term1 && $term2) {
//things to do
}
This might not be the best implementation, but you could always do:
$a=$validator->valid("title");
$b=$validator->valid("text");
if($a && $b) {...}
You can define a function like:
function logical_and($x,$y) {return ($x && $y);}
Since PHP uses call-by-value, this works.
Alternatively, if you can modify the class $validator instantiates, you could make the valid method accept a string or an array. If it's an array, it runs the code that already exists on each item and only returns TRUE if all items are "valid".

Categories