Testing reference equality on a recursive array - php

<?php
$a = [];
$b = [&$a];
$a[] = &$b;
Assuming we have a recursive array - is there any PHP builtin that will test for equality including references?
Standard comparison operators throw a fatal error, and while array_diff doesn't crash it does spit out a ton of notices.
I could always compare print_r($a, true) == print_r($b, true) but this would incorrectly identify $a and $b as the same (Their values may be the same but the references they contain aren't)

Related

Arrays not matching with strict comparison

$c1 = $v1 = array();
$v1['key'] = 'value';
echo '$c1 === $v1: ' . (($c1 === $v1) ? 'true' : 'false'); // prints false
$c1 === $v1 is false. But why? It seems that $v1 is automatically set to a different array then it's origin array automatically. Why it is happening?
Initially $c and $v1 is set to the same array instance. So if I mutate $v1 should not $c reflects the changes as they are set to the same array instance.
These will not be the same, because you explicitly set them to hold different values. The first is empty, while the second holds values.
They are not set to the same reference though, so they are two different variables - when you do
$c1 = $v1 = array();
You create two different arrays. If you want the change of one to reflect in both arrays, you need to make it a reference, by using the & operator in front of the variable identifier, like so.
$v1 = array();
$c1 = &$v1; // $c1 is now a reference to $v1
$v1['key'] = 'value';
echo '$c1 === $v1: ' . (($c1 === $v1) ? 'true' : 'false'); // true!
Notice that you need to reference it after the variable you wish to refer to has been made.
When using a reference like this, it goes both ways - any change to $v1 would be applied to $c1, and the other way around. So they are different variables, but will always hold the same values.
The comparison in the example above holds true because the arrays are exactly the same - not just by reference, but because they hold the same values and keys. If you compare two non-referenced arrays with the exact same values and exact same, matching keys, you would get a true equality too.
var_dump(array('foo') === array('bar')); // false; same keys, different values
var_dump(array('bar') === array('bar')); // true; same keys, same values
var_dump(array('bar') === array('baz' => 'bar')); // false; different keys, same value
Live demo
Passing variables by reference
Because they are two different object, with two different references, with happening one does not affect the other. Just simple like that.
Those arrays will not be the same because the second array has a value. Please run the following code:
<?php
$a = $b = [];
print_r($a);
print_r($b);
$result = ($a === $b) ? 1 : 0;
// The reasult will be 1 because the arrays are both empty.
print_r($result);
$b[0] = 'Ravi';
print_r($a);
print_r($b);
$result = ($a === $b) ? 1 : 0;
// The result will be 0 because the arrays are different.
print_r($result);

Usage of comparison operator after assigning variable

I've seen comparison operators used straight after assigning values to variables in codes such as this:
($i = array_search($v, $b)) !== false // If $v is not in array, outputs false
Or something like this:
$n = 5 <= 5;
echo $n; // Outputs 1;
In the first example, does the comparison operator directly compare the value to array_search(...) or does it compare it to $i, since both of them are in brackets? Would it make a difference if there were no brackets around "$i = array_search(...)?
I've tried looking in the PHP manual on comparison operators, but it does not seem to mention using comparison operators in this way.
Also, in the second example, if there are no brackets, is the comparison operator comparing the value to 5 or to $n?
Could someone please link any documents or articles relating to the usage of comparison operators after assigning variables?
does the comparison operator directly compare the value to array_search(...) or does it compare it to $i
It assigns the value from array_search to $i first, and then evaluates a comparison to that value second.
In your example, array_search will return false on failure.
if( ($i = array_search($v, $b)) !== false ){}
Is totally equivalent to:
$i = array_search($v, $b);
if($i !== false){}
Or:
if( array_search($v, $b) !== false ){}
It's just a convenient shortcut to also assigning the value of $i for use later.

PHP if execution

In PHP if you have the following code does $b get evaluated since $a will cause the if statement to return false?
$a = false;
$b = true;
if ($a && $b) {
// more code here
}
also if $b does get evaluated are there ever circumstances where a portion of an if statement may not be evaluated as the processor already knows that the value to be false?
Evaluation of && is stopped as soon as it hits the false condition.
These (&&) are short-circuit operators, so they don't go to check second condition if the first one true (in case of OR) or false(in case of AND).
Reference: http://php.net/manual/en/language.operators.logical.php
From documentation:
<?php
// --------------------
// 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());
Evaluation of logical expressions is stopped as soon as the result is known.
If $a is false, $b will not get evaluated, as it won't change the ($a && $b) result.
A consequence of that is that if the evaluation of $b requires more ressources than the evaluation of $a, starts your test condition with $a.
But be aware that:
PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code. (Source php docs)
So you should not assume $b is never evaluated if $a is false, as it may change in the future (says php docs).

Javascript-like syntax in php [duplicate]

Javascript employs the conjunction and disjunction operators.
The left–operand is returned if it can be evaluated as: false, in the case of conjunction (a && b), or true, in the case of disjunction (a || b); otherwise the right–operand is returned.
Do equivalent operators exist in PHP?
PHP supports short-circuit evaluation, a little different from JavaScript's conjunction. We often see the example (even if it isn't good practice) of using short-circuit evaluation to test the result of a MySQL query in PHP:
// mysql_query() returns false, so the OR condition (die()) is executed.
$result = mysql_query("some faulty query") || die("Error");
Note that short-circuit evaluation works when in PHP when there is an expression to be evaluated on either side of the boolean operator, which would produce a return value. It then executes the right side only if the left side is false. This is different from JavaScript:
Simply doing:
$a || $b
would return a boolean value TRUE or FALSE if either is truthy or both are falsy. It would NOT return the value of $b if $a was falsy:
$a = FALSE;
$b = "I'm b";
echo $a || $b;
// Prints "1", not "I'm b"
So to answer the question, PHP will do a boolean comparison of the two values and return the result. It will not return the first truthy value of the two.
More idiomatically in PHP (if there is such a thing as idiomatic PHP) would be to use a ternary operation:
$c = $a ? $a : $b;
// PHP 5.3 and later supports
$c = $a ?: $b;
echo $a ?: $b;
// "I'm b"
Update for PHP 7
PHP 7 introduces the ?? null coalescing operator which can act as a closer approximation to conjunction. It's especially helpful because it doesn't require you to check isset() on the left operand's array keys.
$a = null;
$b = 123;
$c = $a ?? $b;
// $c is 123;

Does PHP support conjunction and disjunction natively?

Javascript employs the conjunction and disjunction operators.
The left–operand is returned if it can be evaluated as: false, in the case of conjunction (a && b), or true, in the case of disjunction (a || b); otherwise the right–operand is returned.
Do equivalent operators exist in PHP?
PHP supports short-circuit evaluation, a little different from JavaScript's conjunction. We often see the example (even if it isn't good practice) of using short-circuit evaluation to test the result of a MySQL query in PHP:
// mysql_query() returns false, so the OR condition (die()) is executed.
$result = mysql_query("some faulty query") || die("Error");
Note that short-circuit evaluation works when in PHP when there is an expression to be evaluated on either side of the boolean operator, which would produce a return value. It then executes the right side only if the left side is false. This is different from JavaScript:
Simply doing:
$a || $b
would return a boolean value TRUE or FALSE if either is truthy or both are falsy. It would NOT return the value of $b if $a was falsy:
$a = FALSE;
$b = "I'm b";
echo $a || $b;
// Prints "1", not "I'm b"
So to answer the question, PHP will do a boolean comparison of the two values and return the result. It will not return the first truthy value of the two.
More idiomatically in PHP (if there is such a thing as idiomatic PHP) would be to use a ternary operation:
$c = $a ? $a : $b;
// PHP 5.3 and later supports
$c = $a ?: $b;
echo $a ?: $b;
// "I'm b"
Update for PHP 7
PHP 7 introduces the ?? null coalescing operator which can act as a closer approximation to conjunction. It's especially helpful because it doesn't require you to check isset() on the left operand's array keys.
$a = null;
$b = 123;
$c = $a ?? $b;
// $c is 123;

Categories