Collection Comprehension

Claro takes direct inspiration from Python's powerful "Comprehensions" syntax to provide powerful single-expression operation to encode the common pattern of iterating some collection's elements and putting them into a new collection after potentially filtering and transforming the elements. This allows you to do complex initializations of both mutable and immutable collections directly in-line without having to drop down to multi-line initialization using some form of loop.

List Comprehension

Compare the following loop-based initialization:

Fig 1:


var mutList: mut [string] = mut [];
for (x in [1, 3, 99, 2, 1]) {
  if (x <= 10) {
    lists::add(mutList, strings::repeated("*", x));
  }
}
print(mutList);

Output:

[0.002s][warning][perf,memops] Cannot use file /tmp/hsperfdata_runner/6 because it is locked by another process (errno = 11)
mut [*, ***, **, *]

with the List Comprehension based alternative:

Fig 2:


# The `|` below is read either "for" or "given".
var mutList = mut [strings::repeated("*", x) | x in [1, 3, 99, 2, 1] where x <= 10];
print(mutList);

Output:

mut [*, ***, **, *]

As you can see, taking the time to get comfortable with Comprehension expressions can serve to significantly simplify your code.

Optional: it may be useful to read a bit about the "Set Builder Notation" that inspires this syntax in both Claro and Python.

Set Comprehension

The same convenient Comprehension-based initialization is also supported for Sets. Simply swap the square brackets [...] for curly braces {...}:

Fig 3:


var immutableSet = {strings::repeated("*", x) | x in [1, 3, 99, 2, 1] where x <= 10};
print(immutableSet);

Output:

{**, *, ***}

Notice now, even though the same mapping and filtering is done over the same input collection as in the list comprehension examples above, the output here does not duplicate the entry "*" as Set Comprehension honors set semantics. (However, to be very explicit, strings::repeated("*", 1) was called twice).

Map Comprehension

And finally, Comprehension-based initialization is also supported for Maps. Again, use curly braces {...} instead of square brackets [...], but this time a colon-separated key-value entry is computed from the input collection instead of a single value:

Fig 4:


var mutMap = mut {x : strings::repeated("*", x) | x in [1, 3, 99, 2] where x <= 10};
print(mutMap);

Output:

mut {1: *, 2: **, 3: ***}

Warning: Map Comprehension will Panic at runtime if you attempt to create multiple entries yielding the same key. It's still up for debate whether this is desirable behavior - it's possible that this may be updated to some other model such as "last entry wins". TBD.