7.5 List Annotations
As explained in Lists, the List annotation matches any list, while List.of matches a list whose elements all satisfy another annotation.
#true
#false
#true
The matching form can create an annotation that matches a list with a more specific shape, such as one that has an integer as its first element and a string as is second element. A List.tuple_of annotation is a kind of shorthand for a matching annotation with a list pattern and _ wildcards. Using […] directly for an annotation (i.e., #%brackets) is an even more compact form that it is equivalent to using List.tuple_of.
#true
> [1, "two"] is_a List.tuple_of[Int, String]
#true
#true
#false
A List.tuple_of or […] annotation can end with ... to indicate zero or more elements that match the preceding annotation (but, unlike a list List pattern in matching, the ... is allowed only at the end of the annotation sequence). This means that [String, ...] is another way to write List.of(String), for example.
#true
#true
#true
A List.tuple_of or […] annotation supplies element-specific static information, which is the sense in which it corresponds to a tuple. A tuple-style list annotation can be an alternative to values, for example, that also works in contexts where values is not allowed.
[i, s]
> strs
[[0, "a"], [1, "bb"], [2, "cccc"]]
> str0.length() // static call to String.length
1
> str2.length()
4
A list construction using List or […] propagates element-specific, tuple-style static information to pattern matching, but the List.get or the […] indexing operation (i.e., #%index) is not statically sensitive to a literal index.
> class Posn(x, y):
> class Posn3D(z):
extends Posn
Posn3D(4, 5, 6),
Posn(7, 8)]
> p0.x
1
> p1.z
6
> p0.z
z: no such field or method (based on static information)
> ps[1].x // because all elements are Posns
4
> ps[1].z // not all elements are Posn3Ds
z: no such field or method (based on static information)