Collection literals
A collection literal writes an array, a map or a set in one expression:
trait Shape {
area(): int;
}
struct Square {
int side;
construct(side: int) {
this.side = side;
}
}
extend Square with Shape {
area(): int {
return side * side;
}
}
total(values: long[]): long {
long sum = 0;
for (var value in values) {
sum += value;
}
return sum;
}
main(): int {
# An array literal is an Array of its elements' type.
var primes = [2, 3, 5, 7];
assert(primes.count == 4 && primes[3] == 7, "an Array<int>");
# A trailing comma lets a long literal put one element per line.
var operators = [
"===",
"!==",
"=>",
];
assert(operators[1] == "!==", "an Array<String>");
# Where an Array type is expected, the elements convert to its element type.
assert(total([1, 2, 3]) == 6, "an Array<long> argument");
Shape[] shapes = [Square(2), Square(3)];
assert(shapes[1].area() == 9, "elements convert to the trait type");
# A map literal is a HashMap; a repeated key keeps its last value.
var ages = ["Ada": 36, "Alan": 41];
assert(ages["Alan"] == 41, "a HashMap<String, int>");
# An array literal where a HashSet is expected makes a set.
HashSet<String> keywords = ["if", "else", "if"];
assert(keywords.count == 2, "duplicates are kept once");
# [] and [:] are empty, where the type is declared.
long[] none = [];
HashMap<String, int> nobody = [:];
assert(none.is_empty && nobody.count == 0, "empty collections");
return 0;
}
Arrays
[a, b, c]is a newArray<T>holding the elements in order. A trailing comma is allowed:[a, b, c,].- With no other type to go by,
Tis the first element’s type, and every later element converts to it the way an argument converts to a parameter:[1, 2]is anArray<int>, and[1, "a"]is an error. - Where an array type is expected (a declared variable, a parameter, a
return value, an assignment),
Tis that type’s element type instead, and every element converts to it:long[] a = [1, 2];,Shape[] s = [square, circle];. - Nested literals are typed the same way:
long[][] grid = [[1], [2, 3]];. []is an empty array. It needs a declared type (long[] none = [];), since it has no element to take a type from:
main.pep:2:13: error: empty array literal has no element type; declare the variable's type or write 'Array<T>()'
2 | var a = [];
| ^~
Maps
[k1: v1, k2: v2]is a newHashMap<K, V>holding the entries.KandVcome from the first entry, or from theHashMap<K, V>a declared variable, parameter or return type expects.- A key written twice keeps its last value, as two
insertcalls would. [:]is an empty map, and needs a declared type:HashMap<String, int> none = [:];.
Sets
There is no separate set literal. An array literal where a
HashSet<K> or a
Set<K> is expected converts to one through
the set’s implicit constructor,
which keeps each element once: HashSet<String> keywords = ["if", "else"];.
Types of specializations
A literal never changes a collection’s type after it is built:
Array<int> and Array<long> are different types, and neither converts to
the other.
main.pep:2:21: error: cannot initialize variable 'a' of type 'Array<long>' with a value of type 'Array<int>'
2 | Array<long> a = Array<int>();
| ^~~~~~~~~~