tags:

views:

74

answers:

2

Consider the following PowerShell script:

function Alpha {
# write-output 'Uncomment this line and see what happens.';
return 65;
}

function Bravo {
$x = Alpha;
$y = $x -eq 65;
return $y;
}

$z = Bravo;
echo $z;

On my computer (which is running Windows XP SP3, .NET 4.0, and PowerShell 2.0 RTM), when the script is run, the script's output is as expected (True). However, when "the line" is uncommented (and the script is run again), instead of seeing the same output prepended by Uncomment this line..., I am only seeing 65. Can someone please explain what is going on? Thanks.

+1  A: 

Write-Output just writes an object to the pipeline. If you need a message displayed on the screen, use Write-Host.

So, to take apart what happens here, that was kind of a preliminary. If you uncomment the line, both the string 'Uncomment this line and see what happens.' and the number 65 are outputs of the function, so when calling Bravo the variable $y no longer holds just a single value but instead the array 'Uncomment this line and see what happens.',65.

Now the comparison operators work differently if the left operand is an array instead of a scalar value. If the left operand is an array they simply return all elements from the array where the condition would be $true. In this case, since you compare with 65, it will return all items that are equal to 65. So the result is no longer a boolean but instead an array of objects (or in this case, just a single object) – 65.

Joey
A: 

@Johannes Rössel: Thank you for your explanation. You know, I am a C# programmer (this explains the semicolons) and I am asking this question because an echo debugging statement (a statement which is usually inert in other languages) totally broke my script in strange ways. After tracing down the supposed "strange behavior" for almost an hour, I came up with the script above, narrowing down the "strange behavior" to just two functions.

Thanks to your explanation, now I know two important PowerShell gotchas:

  1. that the echo (Write-Output) statement changes (adds to) a function's return value, and
  2. that the return statement adds to (instead of sets) a function's return value, possibly to form an array.

Indeed, both gotchas can be verified by running the following PowerShell commands:

function Charlie { echo 2; echo 3; echo 5; return 7 }
$a = Charlie
# Nothing is printed.
$a
# Displays the contents of array $a, that is:
# 2
# 3
# 5
# 7

Now I probably want to write all my PowerShell debugging statements with the Write-Warning statement instead. After all, their outputs are colored yellow, so they can be read and distinguished more easily.

Anonymous
(a) You can write debug statements with `Write-Debug` which are then only visible if you set your `$DebugPreference` to something else than `SilentlyContinue`. (b) `return foo` is just a shorthand for `foo; return`. `return` just exits the function while *everything* that is simply dumped to the pipeline from a function belongs to that function's output. `function A { 1; 2; 3 }` returns three values, this has nothing to do with `return` per se.
Joey