title: Why does array_diff_uassoc compares keys whose value do not match
body: <p>I just read <a href="https://stackoverflow.com/q/9458652/576767">that question</a> about strange php behaviour, and even though I could research a bit more, I'm nowhere near understanding it.</p>
  
  <p>I assume the reader has read the original question and is aware of OP's code block and sample, but in short, OP is trying to compare those two arrays, and while the result is good, the compare function seems to be called erratically:</p>
  
  <pre><code>$chomik = new chomik('a');
  $a = array(5, $chomik, $chomik, $chomik);
  $b = array($chomik, 'b', 'c', 'd');
  array_diff_uassoc($a, $b, 'compare');
  </code></pre>
  
  <p><a href="http://php.net/manual/en/function.array-diff-uassoc.php" rel="nofollow noreferrer">The documentation</a> is a bit obscure... but it does state that:</p>
  
  <blockquote>
    <p>The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be <strong>respectively less than, equal to, or greater than</strong> the second.</p>
  </blockquote>
  
  <p>As I understand it, that means that the <code>compare()</code> function should be more like this:</p>
  
  <pre><code>function compare($a, $b) {
      echo("$a : $b&lt;br/&gt;");
      if($a === $b) return 0;
      else if ($a &gt; $b) return 1;
      else return -1;
  }
  </code></pre>
  
  <p>however this still gives very strange results, with even more "duplicates"</p>
  
  <pre>
  1 : 0
  1 : 2
  3 : 1
  2 : 1
  3 : 2
  1 : 0
  1 : 2
  3 : 1
  2 : 1
  3 : 2
  0 : 0
  1 : 0
  1 : 1
  2 : 0
  2 : 1
  2 : 2
  3 : 0
  3 : 1
  3 : 2
  3 : 3
  </pre>
  
  <p>faced with many doubts, I <a href="https://pear.php.net/reference/PHP_Compat-latest/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a3CompatFunctionarray_diff_uassoc.php.html" rel="nofollow noreferrer">read the compat php function</a>, and the part where the check actually happens is interesting:</p>
  
  <pre><code>foreach ($args[0] as $k =&gt; $v) {
      for ($i = 1; $i &lt; $array_count; $i++) {
          foreach ($args[$i] as $kk =&gt; $vv) {
              if ($v == $vv) { // compare keys only if value are the same
                  $compare = call_user_func_array($compare_func, array($k, $kk));
                  if ($compare == 0) {
                      continue 3; // value should not be added to the result
                  }
              }
          }
      }
      $result[$k] = $v;
  }
  </code></pre>
  
  <p><a href="https://github.com/php/php-src/blob/master/ext/standard/array.c#L3938" rel="nofollow noreferrer">here's the actual source</a> (per <a href="https://stackoverflow.com/questions/29421414/why-does-array-diff-uassoc-compares-keys-whose-value-do-not-match#comment47016778_29422485">comment</a>)</p>
  
  <p>The way this code executes the compare function should not be outputting the result we see. Foreach is not able to move back and forth in the keys (AFAIK???), as seems to be the case in the order of the first key here:</p>
  
  <pre>
  1 : 2
  3 : 1
  2 : 1
  </pre>
  
  <p>moreover, it shouldn't check the keys if the value do not match, so why do all these are checked:</p>
  
  <pre>
  1 : 2
  3 : 1
  2 : 1
  3 : 2
  etc...
  </pre>
  
  <p><strong>How can the topmost foreach() in the source code loop back and forth through the keys?!</strong></p>
  
  <p><strong>Why are keys whose values do not match still compared?</strong></p>
  
  <p><strong>Do foreach loops actually continue executing even when they've been <code>continue</code>d?</strong></p>
  
  <p><strong>Is this an example of concurrency?</strong> can call_user_func_array somehow be launched and actually execute the <code>echo("$a : $b&lt;br/&gt;");</code> of the compare function not in the same order they were "launched"??</p>