Update range proposal (#1770)
This commit is contained in:
Родитель
1aed67be2b
Коммит
00ed94d94a
|
@ -4,12 +4,30 @@
|
|||
|
||||
This feature is about delivering two new operators that allow constructing `System.Index` and `System.Range` objects, and using them to index/slice collections at runtime.
|
||||
|
||||
## Detailed Design
|
||||
## Overview
|
||||
|
||||
#### System.Index
|
||||
### System.Index
|
||||
|
||||
C# has no way of indexing a collection from the end, but rather most indexers use the "from start" notion, or do a "length - i" expression. We introduce a new Index expression that means "from the end". The feature will introduce a new unary prefix "hat" operator. Its single operand must be convertible to `System.Int32`. It will be lowered into the appropriate `System.Index` factory method call.
|
||||
|
||||
We augment the grammar for *unary_expression* with the following additional syntax form:
|
||||
|
||||
``` antlr
|
||||
unary_expression
|
||||
: '^' unary_expression
|
||||
;
|
||||
```
|
||||
|
||||
We call this the *index from end* operator. The predefined *index from end* operators are as follows:
|
||||
|
||||
``` c#
|
||||
System.Index operator ^(int fromEnd);
|
||||
```
|
||||
|
||||
The behavior of this operator is only defined for input values greater than or equal to zero.
|
||||
|
||||
Examples:
|
||||
|
||||
```csharp
|
||||
var thirdItem = list[2]; // list[2]
|
||||
var lastItem = list[^1]; // list[Index.CreateFromEnd(1)]
|
||||
|
@ -21,7 +39,30 @@ var multiDimensional = list[3, ^2] // list[3, Index.CreateFromEnd(2)]
|
|||
|
||||
C# has no syntactic way to access "ranges" or "slices" of collections. Usually users are forced to implement complex structures to filter/operate on slices of memory, or resort to LINQ methods like `list.Skip(5).Take(2)`. With the addition of `System.Span<T>` and other similar types, it becomes more important to have this kind of operation supported on a deeper level in the language/runtime, and have the interface unified.
|
||||
|
||||
The language will introduce a new range operator `x..y`. It is a binary infix operator that accepts two expressions. Either operands can be omitted (examples below), and they have to be convertible to `System.Index`. It will be lowered to the appropriate `System.Range` factory method call.
|
||||
The language will introduce a new range operator `x..y`. It is a binary infix operator that accepts two expressions. Either operand can be omitted (examples below), and they have to be convertible to `System.Index`. It will be lowered to the appropriate `System.Range` factory method call.
|
||||
|
||||
We replace the C# grammar rules for *shift_expression* with the following (in order to introduce a new precedence level):
|
||||
|
||||
``` antlr
|
||||
shift_expression
|
||||
: range_expression
|
||||
| shift_expression '<<' range_expression
|
||||
| shift_expression right_shift range_expression
|
||||
;
|
||||
|
||||
range_expression
|
||||
: additive_expression
|
||||
| range_expression? '..' additive_expression?
|
||||
;
|
||||
```
|
||||
|
||||
We call the `..` operator the *range operator*. The built-in range operator can roughly be understood to correspond to the invocation of a built-in operator of this form:
|
||||
|
||||
``` c#
|
||||
System.Range operator ..(Index start = 0, Index end = ^0);
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```csharp
|
||||
var slice1 = list[2..^3]; // list[Range.Create(2, Index.CreateFromEnd(3))]
|
||||
|
|
Загрузка…
Ссылка в новой задаче