Difference between list, tuple, sequence, sequence, iteration, array, etc. In Ceylon

Ceylon has several different concepts for things that can be considered as some kind of array: List , Tuple , Sequence , Sequential , Iterable , Array , Collection , Category , etc. How are these types different and when should I use them?

+5
source share
2 answers

The best place to start learning these things at a basic level is the Ceylon tour . And the place to learn about these things in depth is the API module . It is also useful to see the source files for these .

Like all good modern programming languages, the first few interfaces are super abstract. They are built around one official member and provide their functionality through a bunch of default and actual members. (In programming languages ​​created prior to Java 8, you may have heard these “traits” to distinguish them from traditional interfaces, which have only formal members and no functionality.)

Category

Let's start by discussing the Category interface. It represents types that you can ask: "does this collection contain this object", but you may not be able to pull any member out of the collection. Formal member:

 shared formal Boolean contains(Element element) 

An example is the totality of all factors of a large number - you can effectively check whether any integer is a factor, but it is not effective to get all the factors.

Iterable

The Category subtype is the Iterable interface. It represents types from which you can get each element one at a time, but it is not necessary to index the elements. Elements may not have a clearly defined order. Elements may not even exist, but are generated on the fly. A collection can even be infinitely long! Formal member:

 shared formal Iterator<Element> iterator() 

An example is a stream of characters, for example, a standard one. Another example is the range of integers provided to the for loop, for which more memory is more efficient to generate numbers one at a time.

This is a special type in Ceylon and can be abbreviated {Element*} or {Element+} depending on whether the iterable can be empty or definitely not empty, respectively.

Collection

One of the Iterable subtypes is the Collection interface. He has one official member:

 shared formal Collection<Element> clone() 

But it does not really matter. The important thing that defines Collection is this line in the documentation:

All Collection necessary to support a clearly defined concept of the value of equality, but the definition of equality depends on the type of collection.

Basically, Collection is a collection whose structure is well defined to be equivalent and cloned. This requirement for a well-defined structure means that this is the last of the super abstract interfaces, and the rest will look like more familiar collections.

List

One of the subtypes of Collection is the List interface. It is a collection whose elements we can get by index ( myList[42] ). Use this type when your function requires the array to retrieve things, but it doesn't matter if it is mutable or immutable. It has several formal methods, but an important one from its other supertype Correspondence :

 shared formal Item? get(Integer key) 

Sequence, sequence, empty

The most important subtype of List is the Sequential interface. It is 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 collections
  • Sequence (aka [Element+] ), which represents non-empty collections.

Because collections are immutable, there are many things you can do with them that you cannot do with mutable collections. Firstly, numerous operations may fail with null in empty lists, for example, reduce and first , but if you first check that the type is Sequence , then you can guarantee that these operations will always succeed, because the collection cannot become empty later (they are immutable in the end).

Tuple

A special subtype of Sequence is Tuple , the first true class specified here. Unlike Sequence , where all elements are limited to one type of 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 the same types in that order.

Array

Another subtype of List is Array , which is also a true class. This is a familiar Java array, a mutable list of elements of a fixed size.

+8
source

drhagen already answered the first part of your question very well, so I just want to say a little about the second part: when do you use which type?

In the general case: when writing a function, so that it takes on the most general type that supports the operations you need. So far so obvious.

Category is very abstract and rarely useful.

Iterable should be used if you expect some stream of elements that you are going to iterate over (or use stream operations like filter , map , etc.).

Another thing worth considering about Iterable is that it has extra syntactic sugar in named arguments:

 void printAll({Anything*} things, String prefix = "") { for (thing in things) { print(prefix + (thing?.string else "<null>")); } } printAll { "a", "b", "c" }; printAll { prefix = "X"; "a", "b", "c" }; 

Try it online

Any parameter of type Iterable can be represented as a list of comma-separated arguments at the end of the list of named arguments. I.e

 printAll { "a", "b", "c" }; 

equivalently

 printAll { things = { "a", "b", "c" }; }; 

This allows you to create expressions in the style of DSL; tour contains some nice examples.

Collection , like Correspondence , is quite abstract and in my experience is rarely used directly.

List sounds like it should be a frequently used type, but in fact I don’t remember it much. I do not know why. I seem to have missed it and declared my parameters as Iterable or Sequential .

Sequential and Sequence are when you need an immutable list of fixed lengths. It also has some syntactic sugar: variative methods like void foo(String* bar) are shortcuts to the Sequential or Sequence parameter. Sequential also allows you to use the nonempty operator, which often works great in combination with first and rest :

 String commaSeparated(String[] strings) { if (nonempty strings) { value sb = StringBuilder(); sb.append(strings.first); // known to exist for (string in strings.rest) { // skip the first one sb.append(", ").append(string); // we don't need a separate boolean to track if we need the comma or not :) } return sb.string; } else { return ""; } } 

Try it online

I usually use Sequential and Sequence when Im going to iterate over a stream several times (which can be expensive for a general Iterable ), although List may be the best interface for this.

Tuple should never be used as a Tuple (except in the rare case when you abstract above them), but with the syntax of sugar [X, Y, Z] it is often useful. You can often specify the Sequential member in Tuple in a subclass, e. d. The superclass has <String|Integer>[] elements , which in one subclass is known as [String, Integer] elements .

Array Ive was never used as a parameter type, rarely just as a class to create and use.

+3
source

Source: https://habr.com/ru/post/1241881/


All Articles