PowerShell and the Heisenberg Principle

While developing the PowerShell debugger for PrimalScript 2007 we tested with a large number of scripts. Pretty much anything we could lay our hands on. The following script was one of them.

function AreArraysEqual($a1, $a2) {

    $enum1 = $a1.GetEnumerator()
    $enum2 = $a2.GetEnumerator()   
    #"$enum1"
    while ($enum1.MoveNext() -and $enum2.MoveNext()) {
      if ($enum1.Current -ne $enum2.Current) {
            return $false
      }
    }
    return $true
}
$a1 = @(1, 2, 3, 5)
$a2 = @(3, 1, 2, 4)
AreArraysEqual $a1 $a2

 

Please note that the code is simplified and error checks are removed for that purpose.

What happened was that this code reported correctly that the two arrays where unequal, whereas when run in the debugger it would report them as equal. A quick investigation revealed that the debugger’s variable watch routines where the reason.

To illustrate the effect you can uncomment the "$enum1" line in the script above. What happens is that when you "output" an enumerator it actually enumerates the array and prints the array. This leaves the enumerator at the end of the array rather than at the beginning and the following while loop never gets executed.

In the software developer world this is called a "side effect" but nonetheless very undesirable. Simply observing an object should not alter its state.

At any rate, the next time you seed your PowerShell code with Write-Debug statements to see the content of variables, consider that the very observation of an object can alter its state.