Sequences are a special type in the language and can be thought of as a collection of elements, similar to an array.
In contrast to arrays, sequences do not imply a specific form of data storage, but can represent any collection of elements that is accessible in a specific order. This could be an array (and as a matter of fact, all arrays can be treated as a sequence) or a different data store, such as a linked list, a binary tree or a custom collection implementation.
Sequences can also represent non-static data that is retrieved or generated on the fly when the sequence is enumerated. For example, you could implement a sequence that calculates all digits of Pi, or retrieves RSS headlines downloaded from a server.
As a result, sequences are not a concrete type that can be instantiated – one cannot "new up a new sequence", because it would be undefined where its data would come from. Instead, sequences are used as base types to consume data where the exact storage is unknown.
For example, a method could be written that prints out a
sequence of Integer to the console. That method could then be invoked with any number of different types that adhere to the sequence protocol, no matter where those Integers come from. By contrast, if the method were declared to take an Array or a generic
List<Integer>, it would be much more restrictive.
Sequence types are expressed with the
sequence of keyword followed by a type name.
var SomeIntegers: sequence of Integer;
The most common operation on a sequence is to iterate it using a
for each Loop loop, a variant of
for loop that executes a statement (or block of statements) once for each item in the sequence:
for each i in SomeIntegers do writeLn(i);
var FewerSortedIntegers := from i in SomeIntegers where i ≥ 20 order by i; for each i in FewerSortedIntegers do writeLn(i);
In the above example, the sequence of Integers will be filtered to include only those values larger or equal to 20, and then sorted numerically.
In addition to Array, most collection types on the various platforms, including the
List<Integer> type in Elements RTL are compatible with sequences. Sequences can easily be implemented using Iterators or
for Loop Expressions.
Available only on .NET, parallel sequences are a special type of sequence that can be iterated in parallel in a multi-threaded environment with .NET's parallelism APIs. It maps to the
ParallelQuery<T> system type.
var data: parallel sequence of Integer; data.ForEach(a -> DoSomethingParallelWith(a));
The Parallel Sequences are available on the .NET platform only.
Available only on .NET only, queryable sequences are a special type of sequence where LINQ expressions applied to the sequence will be compiled to executable code, but converted into meta data that can be used to perform operations on the sequence at runtime.
For example, using LINQ to SQL or DA LINQ, a
from expression on a sequence of database objects can be translated into SQL code that could perform the operations on the back-end database. Rather than fetching an entire data table and then filtering it locally, the filtering can be done by the database engine.
var AllUsers := rda.GetDataTable<Users>; var NewUsers := from u in AllUsers where u.DateSignedUp > DateTime.Now.Add(-1); for each u in NewUsers do writeLn(u.Name);
In this case, the "
where" clause would get translated to SQL to only fetch the most recent users from the database instead of all of them – potentially saving a lot of network bandwidth and memory.
queryable sequence maps to the
IQueryable<T> system type.
The Queryable Sequences are available on the .NET platform only.
var lItems: async sequence of String := ...; await for each i in lItems do writeLn(el); writeLn("Done");
Asynchronous Sequences are expressed by the
async sequence keyword, and map to the
IAsyncSequence<T> platform type. They can easily be created by implementing an Iterator with an
async sequence of X result type.
The Asynchronous Sequences are available on the .NET platform only.