Ceylon has several different concepts for things that might all be considered some kind of array: List
, Tuple
, Sequence
, Sequential
, Iterable
, Array
, Collection
, Category
, etc. What's is different about these these types and when should I use them?
The best place to start to learn about these things at a basic level is the Ceylon tour. And the place to learn about these things in depth is the module API. It can also be helpful to look at the source files for these.
Like all good modern programming languages, the first few interfaces are super abstract. They are built around one formal member and provide their functionality through a bunch of default and actual members. (In programming languages created before Java 8, you may have heard these called "traits" to distinguish them from traditional interfaces which have only formal members and no functionality.)
Let's start by talking about the interface Category
. It represents types of which you can ask "does this collection contain this object", but you may not necessarily be able to get any of the members out of the collection. It's formal member is:
shared formal Boolean contains(Element element)
An example might be the set of all the factors of a large number—you can efficiently test if any integer is a factor, but not efficiently get all the factors.
A subtype of Category
is the interface Iterable
. It represents types from which you can get each element one at a time, but not necessarily index the elements. The elements may not have a well-defined order. The elements may not even exist yet but are generated on the fly. The collection may even be infinitely long! It's formal member is:
shared formal Iterator<Element> iterator()
An example would be a stream of characters like standard out. Another example would be a range of integers provided to a for loop, for which it is more memory efficient to generate the numbers one at a time.
This is a special type in Ceylon and can be abbreviated {Element*}
or {Element+}
depending on if the iterable might be empty or is definitely not empty, respectively.
One of Iterable
's subtypes is the interface Collection
. It has one formal member:
shared formal Collection<Element> clone()
But that doesn't really matter. The important thing that defines a Collection
is this line in the documentation:
All
Collection
s are required to support a well-defined notion of value equality, but the definition of equality depends upon the kind of collection.
Basically, a Collection
is a collection who structure is well-defined enough to be equatable to each other and clonable. This requirement for a well-defined structure means that this is the last of the super abstract interfaces, and the rest are going to look like more familiar collections.
One of Collection
's subtypes is the interface List
. It represents a collection whose elements we can get by index (myList[42]
). Use this type when your function requires an array to get things out of, but doesn't care if it is mutable or immutable. It has a few formal methods, but the important one comes from its other supertype Correspondence
:
shared formal Item? get(Integer key)
The most important of List
's subtypes is the interface Sequential
. It represents an immutable List
. Ceylon loves this type and builds a lot of syntax around it. It is known as [Element*]
and Element[]
. It has exactly two subtypes:
Empty
(aka []
), which represents empty collectionsSequence
(aka [Element+]
), which represents nonempty collections.Because the collections are immutable, there are lots of things you can do with them that you can't do with mutable collections. For one, numerous operations can fail with null
on empty lists, like reduce
and first
, but if you first test that the type is Sequence
then you can guarantee these operations will always succeed because the collection can't become empty later (they're immutable after all).
A very special subtype of Sequence
is Tuple
, the first true class listed here. Unlike Sequence
, where all the elements are constrained to one type Element
, a Tuple
has a type for each element. It gets special syntax in Ceylon, where [String, Integer, String]
is an immutable list of exactly three elements with exactly those types in exactly that order.
Another subtype of List
is Array
, also a true class. This is the familiar Java array, a mutable fixed-size list of elements.