6

The following powershell script

"one","two","three" | % { "$(($l++)): $_" }

will print

1: one
2: two
3: three

However, after remove the bracket around $l++

"one","two","three" | % { "$($l++): $_" }

it will print

: one
: two
: three
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
ca9163d9
  • 27,283
  • 64
  • 210
  • 413

4 Answers4

12

This is because $l++ is a voidable statement. In powershell certain types of expressions, when used as statements, are not displayed. Voidable statements include assignments and the increment/decrement operators. When they are used in an expression, they return a value, but when they’re used as a standalone statement, they return no value. It is very well explained in Windows Powershell in Action by Bruce Payette:

The increment and decrement operators were almost not included in PowerShell because they introduced a problem. In languages such as C and C#, when you use one of these operators as a statement: $a++ nothing is displayed. This is because statements in C and C# don’t return values. In PowerShell, however, all statements return a value. This led to confusion. People would write scripts like this:

$sum=0
$i=0
while ($i -lt 10) { $sum += $i; $i++ }
$sum

and be surprised to see the numbers 1 through 10 displayed. This was because $a++ returned a value and PowerShell was displaying the results of every statement. This was so confusing that we almost removed these operators from the language. Then we hit on the idea of a voidable statement. Basically, this means that certain types of expressions, when used as statements, are not displayed. Voidable statements include assignments and the increment/decrement operators. When they are used in an expression, they return a value, but when they’re used as a standalone statement, they return no value. Again, this is one of those details that won’t affect how you use PowerShell other than to make it work as you expect. (source: Windows Powershell in Action)

jon Z
  • 15,838
  • 1
  • 33
  • 35
4

I believe this was a design decision made by the PowerShell team to avoid surprises due to PowerShell outputting return values. Many C/C# folks would expect the following function to only output 1 not @(0,1).

function foo {
  $i = 0
  $i++
  $i
}

So the statement form $i++ doesn't output the value of $i before it is incremented. If you want that behavior, PowerShell allows you to get that behavior by putting the increment (or decrement) statement directly inside an expression e.g.:

function foo {
  $i = 0
  ($i++)
  $i
}

This will output @(0,1).

Bruce Payette discusses this in Chapter 5 of Windows PowerShell in Action 2nd Edition. The increment and decrement operators are "voidable statements". Quoting from the book:

Basically, this means that certain types of expressions, when used as statements, are not displayed. Voidable statements include assignment statements and the increment/decrement operators. When increment and decrement are used in an expression, they return a value, but when they’re used as a standalone statement, they return no value.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
1

That is because $l++ doesn't return anything, :

$l = 0
$l++   #nothing
$l #gives 1
$l++   #nothing
($l++)  #gives 2

This is done so that there is no confusion when you are returning to pipeline. Effectively,

$l++ is $l = $l+ 1, so it doesn't return anything.

What you want to see is $l = $l + 1; $l, which is why you have to do ($l++).

manojlds
  • 290,304
  • 63
  • 469
  • 417
0

I think there are two tasks it needs to do:

  1. Execute $l++ (increment the variable) which happens on the inner parenthesis
  2. Retrieve $l's value which happens in the outer parenthesis.

Here is a illustration of this:

$l = 0
"$($l++ ; $l)"

Outputs: 1 where

$l = 0
"$($l++)"

Doesn't output anything.

In order to receive output I need two statements inside the sub-expression. Otherwise the only thing that happens is that $l is incremented but its value is not retrieved.

Andy Arismendi
  • 50,577
  • 16
  • 107
  • 124