Search code examples
ceylon

Initialising Sequential values with for loop?


Is there any way to initialize a Sequential value not in one fellow swoop?

Like, can I declare it, then use a for loop to populate it, step by step?

As this could all happen inside a class body, the true immutability of the Sequential value could then kick in once the class instance construction phase has been completed.

Example:

Sequential<String> strSeq;

for (i in span(0,10)) {
    strSeq[i] = "hello";
}

This code doesn't work, as I get this error:

Error:(12, 9) ceylon: illegal receiving type for index expression: 'Sequential' is not a subtype of 'KeyedCorrespondenceMutator' or 'IndexedCorrespondenceMutator'

So what I can conclude is that sequences must be assigned in one statement, right?


Solution

  • The square brackets used to create a sequence literal accept not only a comma-separated list of values, but also a for-comprehension:

    String[] strSeq = [for (i in 0..10) "hello"];
    

    You can also do both at the same time, as long as the for-comprehension comes last:

    String[] strSeq = ["hello", "hello", for (i in 0..8) "hello"];
    

    In this specific case, you could also do this:

    String[] strSeq = ["hello"].repeat(11);
    

    You can also get a sequence of sequences via nesting:

    String[][] strSeqSeq = [for (i in 0..2) [for (j in 0..2) "hello"]];
    

    And you can do the cartesian product (notice that the nested for-comprehension here isn't in square brackets):

    [Integer, Character][] pairs = [for (i in 0..2) for (j in "abc") [i, j]];
    

    Foo[] is an abbreviation for Sequential<Foo>, and x..y translates to span(x, y).