Indexes and Ranges

Elements supports the Index and Range types introduced by .NET Core 3.0, and brings them across to all platforms, including Classic .NET.

Indexes

An Index represents a position in an ordered collection, counting either from the start (e.g "the fifth element") or from the end (e.g. "the third element from the end").

It is worth nothing hat a reverse index is independent of the size of the collection it will be applied to. For example, an index specifying "the third item from the end" would return "l" when used to index the string "Hello", and "d" when used on the string "Hello World". Forward-indexes are zero-based, and reverse indexes are one-based.

In C#, the caret operator can be used to create a reverse index, and a regular integer literal creates a forward index.

var hello = "Hello";
writeLn(hello[0]); // prints 'h'
writeLn(hello[^1]); // prints 'o'

Ranges

A Range is a set of two indexes representing a start and end offset in a collection. Either offset can be a forward or a reverse index, so a range could represent "elements three to seven", but also, for example, "elements 2 to the second from last".

In C#, the .. operator can be used to create a range:

var range = 1..^2;
writeLn("Hello World"[range]); // prints 'ello Worl'
writeLn("abc"[range]); // prints 'b'

The start and/or the end of a range can be omitted, and will be implied to be 0, or ^1,. respectively:

writeLn("Hello World"[..4]);  // prints 'Hello'
writeLn("Hello World"[..^4]); // prints 'Hello W'
writeLn("Hello World"[4..]);  // prints 'o World'
writeLn("Hello World"[^4..]); // prints 'orld'
writeLn("Hello World"[..]);   // prints 'Hello World'

Language Limitations

Right now, only C# has a native syntax for Indexes and Ranges. In all other languages you can use the Index and Range type (from System or RemObjects.Elements.System) by name to construct an index or a range.

var i := Index.FromEnd(5); // ^5
var r := Range.StartAt(i); // ^5..^1
var q := new Range(Index.FromStart(2), Index.FromEnd(5)); // 2..^5
var i = ^5;
var r = ^5..^1;
var q = 2..^5;
let i = Index.FromEnd(5) // ^5
let r = Range.StartAt(i) // ^5..^1
let q = Range(Index.FromStart(2), Index.FromEnd(5)) // 2..^5
var i = Index.FromEnd(5); // ^5
var r = Range.StartAt(i); // ^5..^1
var q = new Range(Index.FromStart(2), Index.FromEnd(5)); // 2..^5
Dim i = Index.FromEnd(5) // ^5
Dim r = Range.StartAt(i) // ^5..^1
Dim q = New Range(Index.FromStart(2), Index.FromEnd(5)) // 2..^5