Initialising Sequential values with for loop?

77 views Asked by At

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?

3

There are 3 answers

2
gdejohn On BEST ANSWER

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).

0
Lucas Werkmeister On

Yes, several language guarantees hinge on the immutability of sequential objects, so that immutability must be guaranteed by the language – it can’t just trust you that you won’t mutate it after the initialization is done :)

Typically, what you do in this situation is construct some sort of collection (e. g. an ArrayList from ceylon.collection), mutate it however you want, and then take its .sequence() when you’re done.

Your specific case can also be written as a comprehension in a sequential literal:

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

If you know upfront the size of the sequence you want to create, then a very efficient way is to use an Array:

value array = Array.ofSize(11, "");
for (i in 0:11) {
    array[i] = "hello";
}
String[] strSeq = array.sequence();

On the other hand, if you don't know the size upfront, then, as described by Lucas, you need to use either:

  • a comprehension, or
  • some sort of growable array, like ArrayList.