Req #34291 [Opn->Csd]: reference comparison: $a isIdenticalTo $b
| From: | krakjoe@php.net | Date: | Sun, 27 Mar 2016 08:44:39 +0000 |
| Subject: | Req #34291 [Opn->Csd]: reference comparison: $a isIdenticalTo $b | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-200154@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=34291&edit=1
ID: 34291
Updated by: krakjoe@php.net
Reported by: csaba at alum dot mit dot edu
Summary: reference comparison: $a isIdenticalTo $b
-Status: Open
+Status: Closed
Type: Feature/Change Request
-Package: Feature/Change Request
+Package: *General Issues
PHP Version: 5.1.0RC1
-Assigned To:
+Assigned To: krakjoe
Block user comment: N
Private report: N
New Comment:
Sometime between version 5.3 and 5.4, the restriction that caused you to request this feature was
lifted.
Sorry about the wait :)
Previous Comments:
------------------------------------------------------------------------
[2005-08-30 20:28:16] csaba at alum dot mit dot edu
OK, I was a bit hasty in what I recommended. In particular, there are two distinct cases: In one
case, we want to know whether two references are the same. In the second, we'd like to know
whether the values of two references are the same. The latter is the same as === except for arrays.
So, I have written a function, isIdentical to do both of these. For the case of arrays and ===, I
poke a new element onto one array and see if it shows up on the other. For the reference checking,
I take a similar approach, except that one has to be careful with arrays, because any reference
pointing to the original array that is poked is destroyed so this has to be fixed up. That is the
reason for the two foreach loops - it detects self references that were destroyed and fixes them.
The whole methodology employed in the example below - see what happens if you poke at it - does not
give one the warm fuzzies. I'd still prefer to see isIdentical implemented as a native PHP
function.
function isIdentical(&$ref1, &$ref2, $referencesP=false) {
// if $referencesP is true, isIdentical returns true
// iff $ref1====$ref2. That is, if
// $ref2=somethingElse changes $ref1, to
// somethingElse, too (Ie. the same reference)
// if $referencesP is false, isIdentical is the same
// as $ref1===$ref2 for non objects/arrays.
// For objects/arrays $ref1===$ref2 iff a change
// in (a property of) $ref2 is reflected in $ref1
// (ie. the same object/array)
if (gettype($ref1)!=($type=gettype($ref2))) return false;
if ($arrayP=($type=="array")) {
if (count($ref1)!=count($ref2)) return false;
if (!$referencesP) {// are $ref1,$ref2 the same object
$test = "isSameObjectTest";
while (array_key_exists($test, $ref2))
$test .= rand();
if (array_key_exists($test, $ref1)) return false;
$ref2[$test] = 13;
$result = array_key_exists($test,$ref1);
unset ($ref2[$test]);
return $result; }
$aType = array();
foreach ($ref2 as $key=>$val)
$aType[$key] = gettype($val); }
// accounts for objects, too.
elseif (!$referencesP) return $ref1===$ref2;
$tmp = $ref2;
$ref2 = ($type=="string") ? 13 : "fred";
$result = gettype($ref1)!=$type;
// now we must repair the damage
$ref2 = $tmp;
if ($arrayP)
foreach ($ref2 as $key=>&$ref)
if ($aType[$key]!=gettype($ref)) $ref=&$ref2;
return $result;
}
Csaba Gabor from Vienna
references:
//for comparison, see http://php.net/operators.comparison
//http://at2.php.net/manual/en/language.operators.array.php
//http://at2.php.net/manual/en/language.oop5.object-comparison.php
Tested with:
<?php
$a = array(7); $a[] = &$b;
$b = array(8); $b[] = &$a;
$c = array(9); $c[] = &$a;
print "<pre>";
print "GLOBALS test " . (isIdentical($GLOBALS,
$GLOBALS["GLOBALS"], true) ? "passed" : "failed");
print "\nDouble test " . (isIdentical($b[1],
$c[1], true) ? "passed\n" : "failed\n");
$c[2] = "test from c";
$b[3] = "test from b";
$a[4] = "test from a";
var_dump($a); print "\n";
var_dump($b); print "\n";
var_dump($c); print "</pre>";
?>
------------------------------------------------------------------------
[2005-08-28 23:02:51] csaba at alum dot mit dot edu
Description:
------------
I would like to recommend a (boolean) operator:
$ref1 isIdenticalTo $ref2
to compare whether two references are identical.
A main use of this is in tree traversal. For example:
$a = array(7);
$a[] = &$a; // we now have a self reference
print $a[1][1][1][0]; // => 7. All is OK
if ($a==$a[1]) print "same"; // Fails
Both $a==$a[1] and $a===$a[1] will fail because the nesting level is too deep. This is in agreement
with the documentation, which says that values are tested.
If I could do isIdenticalTo however (one could not use ==== with a straight face), then by placing
the references of subarrays encountered onto an $aVisited array, I could run through them myself and
check with isIdenticalTo and thus avoid exceeding a nesting level.
An example where this (appropriately) happens is with $GLOBALS, since $GLOBALS["GLOBALS"]
isIdenticalTo $GLOBALS.
Thanks for considering this,
Csaba Gabor from Vienna
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=34291&edit=1