2

Consider the following: (Note: I modified the output slightly for readability)

~> @(11..20)
11, 12, 13, 14, 15, 16, 17, 18, 19, 20

~> @(11..20+1)
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1

~> @(1+11..20)
InvalidOperation: Method invocation failed because [System.Object[]] does not contain a method named 'op_Addition'.

I've always found this array addition syntax to be confusing, and would much prefer something like @(1,11..20).

At any rate, why does the 3rd operation not work identically to the 2nd?

Is it because 1 is not considered an array, even though it is being given as part of the array definition syntax?

~> @(1,2+11..20)
1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

If that's the case then why does @(11..20+1) work as expected?

I can work around this in a few ways...

~> @(@(1)+11..20)
1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

~> @(,1+11..20)
1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

~> @(11..20+1) | Sort
1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

But those seem pretty ugly, inelegant, and the latter workaround doesn't account for instances where I don't actually want to sort the array.

The one that makes the most sense is @(,1+11..20), though it's not particularly pleasing. Is there a more proper way to achieve the desired result in the desired order, without the additional syntax or piping?

None of the examples in the official documentation demonstrate this particular permutation.

Thanks.

1
  • You don't need the @( ). Commented Feb 27, 2022 at 1:47

1 Answer 1

3

@(...), PowerShell's array-subexpression operator - which enumerates whatever ... outputs and collects it in an [object[]] array - is only applied after ... is evaluated, so we can leave it aside in this discussion.

Generally, in PowerShell it is the type of the LHS of an operation that determines what type-appropriate overload of the operation applies.

  • In 11..20 + 1, the LHS is an array, due to use of .., the range operator, so the + operator performs array concatenation.

  • In 1 + 11..20, the LHS is a scalar - an [int] instance - so the + operator tries to perform numerical addition, which, however, fails, because adding an array to a number doesn't make sense and therefore isn't supported.

If you want to perform array concatenation with a scalar LHS, wrap that LHS in an aux. array using the unary form of ,, the array constructor operator:

, 1 + 11..20

Alternatively, use one of the following:

  • @(1) + 11..20
  • [array] 1 + 11..20

If you don't know ahead of time whether the LHS actually is already an array, but you want it treat it as such if it isn't, the [array] cast is the most efficient solution:

[array] 1 + 11..20

Note that the cast only applies to 1, based on PowerShell's operator precedence rules.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it makes a lot more sense understanding the role of @() and separating it from the array addition, rather than (inaccurately) thinking about the whole thing as being an array definition. Also re-internalizing the LHS rule is helpful. I've frequently struggled with code such as foreach($x in $y) when $y has the ability to end up as an "array" with a single item. I prefer untyped languages but these are the situations where it bites me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.