PS C:\> $a = 0..10
PS C:\> # Negative indexing
PS C:\> $a[-1]
10
PS C:\> $a[-3]
8
PS C:\> # List slices (a[start..end])
PS C:\> $a[2..8]
2
3
4
5
6
7
8
PS C:\> # List slices with negative indexing
PS C:\> $a[-4..-2]
7
8
9
PS C:\> # List slices with step (a[start..end:step])
PS C:\> $a[2..8:2] # 2 step
PS C:\> # 2 4 6 8
PS C:\>
PS C:\> # List slices with negative step (2 step)
PS C:\> $a[0..10:-2]
PS C:\> # 10 8 6 4 2 0
PS C:\>
one useful example with this: check palindrome
$s = 'hello world'
$s[0..$s.length:-1] -eq $s
@p0W3RH311 I'm a bit confused. I _think_ what you're asking for is actually just a step option on ranges correct? Or is there something wrong with slices that you want changed/fixed? And your palindrome example should be
-join $s[($s.length-1)..0] -eq $s
(You need the -join because slices on strings returns character arrays. The unary -join glues the characters back into a string.)
In some other languages this is done with a slightly different syntax: 0..2..$n which might perhaps be more intuitive. That said, I'd imagine there are more changes that would be necessary to make that a working solution.
@p0W3RH311: Since all but the last 2 commands in your code relate to the _new_ functionality you're looking for (stepping), can I suggest you remove the others, which simply demonstrate _current_ behavior (or at least make the distinction clear)?
Stepping sounds like a handy feature to have, but note that it would have to be implemented on the _range operator_ (..), given that there's no special array-subscript syntax in PowerShell.
If that is feasible, however, the up-side is that stepping then becomes available even outside the context of array slicing.
There are other slicing improvements I think would be great, but they indeed would require special handling inside an array index - see #7940
PS C:\> # List slices with step (a[start..end:step])
PS C:\> $a[2..8:2] # 2 step
PS C:\> # 2 4 6 8
PS C:\>
PS C:\> # List slices with negative step (2 step)
PS C:\> $a[0..10:-2]
PS C:\> # 10 8 6 4 2 0
PS C:\>
I use below to do same. I agree it will be easier if we get option to splice array with steps.
$a = (0..10)
$a[2..8] | foreach { if($_ % 2 -eq 0) {$_}}
$a[-1..-9] | foreach { if($_ % 2 -eq 0) {$_}}
Don't have time to find the official C# 8 docs but this blog post docs the new "range" operator in C#. Is there anything here that PS could borrow? https://neelbhatt.com/2018/05/26/c-8-0-expected-features-part-iv-something-new-for-indexes-and-ranges/
Thanks, @rkeithhill - I had no idea this was coming. It looks like _stepping_, as requested by this issue, is not part of what's coming to C# 8, so the discussion is more relevant to #7940 - I suggest we continue the discussion there.
@BrucePay Is there anything that prevents us form using the C#8 syntax?
So that the range operator, within the context of a collection indexing operation, gets hat-support :)
I see no reason why the hat/caret character couldn't be used to denote an index token... And the range operator could then have overloads that take index types, and give out the c# style of indexing object.
Good points, but can I suggest we limit _this_ issue to the _stepping_ proposal and continue the _range_ discussion in #7940, which already has more detail, notably in https://github.com/PowerShell/PowerShell/issues/7940#issuecomment-427503911?
@p0W3RH311 C# doesn't appear to do stepping (at least not yet). Also remember that ranges are not just used for slices e.g.
foreach ($i in 1..10) { $i }
1..10 | foreach { $_ * 2 }
$x = 1..5; $myArray[$x]
etc. so restricting the hat operator to slices would be a little weird. And ^ as a prefix operator is somewhat problematic since you can have a function named ^ (I did for years). Finally PowerShell already does most of what C# will do but with some strange idiosyncrasies, so I suspect that adding the hat operator now would just add to the confusion.
Getting back to stepping, my thought had been to simply do, as @vexx32 suggests, 1..10..2. (Another planned but unimplemented feature from V1 time frame. )
@BrucePay regarding use of hat operator and slicing from arrays, my inclination would be to do as c# does and simply adopt it's Index and Range data types.
A ^5 would be an index value owing to the hat operator. A 4..^2 is a true Range type for the same reason, the 4 being implicitly converted to an index type.
If we want to allow more versatile uses of Index type items, we could use 5^ for 'from-start' indexes and ^5 for 'from-end' indexes. This would be largely unnecessary, though, as regular integers should be able to be converted to an index value pretty easily as a from-start value in any context where it is needed.
@vexx32 If PowerShell didn't have ranges, then I might agree. If we were starting from scratch I might agree. But PowerShell already has ranges with defined semantics which are not the same as the upcoming semantics for C#. Replacing the _existing_ range behaviour would certainly be a BIG breaking change. Trying to retrofit/merge the new C# semantics into PowerShell would make ranges much more complicated and confusing.
Should we have new syntax for slices? My eyes bleed everytime I write $array[2..($array.Length - 2)].
@powercode:
Indeed we should - and the discussion of their specifics is well underway in #7940 (the only thing not covered there is _stepping_, hence my previous suggestion to limit discussion _here_ to stepping - though perhaps we should merge the two discussions).
Did I mention #7940?
Before I forget: please check out #7940.
P.S.: #7940 is worth a look.
P.P.S.: I think #7940 is devoted to that very topic.
@mklement0 馃槉
Most helpful comment
Should we have new syntax for slices? My eyes bleed everytime I write
$array[2..($array.Length - 2)].