Ceylon中List、Tuple、Sequence、Sequential、Iterable、Array等的区别

Difference between List, Tuple, Sequence, Sequential, Iterable, Array, etc. in Ceylon

锡兰对可能都被视为某种数组的事物有几个不同的概念:ListTupleSequenceSequentialIterableArrayCollectionCategory 等。这些类型有什么不同,我应该在什么时候使用它们?

从基础开始了解这些内容的最佳起点是 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

像所有优秀的现代编程语言一样,前几个接口是超级抽象的。它们围绕一个正式成员构建,并通过一组默认成员和实际成员提供功能。 (在 Java 8 之前创建的编程语言中,您可能听说过这些称为 "traits" 以区别于只有正式成员而没有功能的传统接口。)

类别

让我们从界面开始说起Category。它表示您可以询问 "does this collection contain this object" 的类型,但您不一定能够从 collection 中获取任何成员。它的正式成员是:

shared formal Boolean contains(Element element)

一个例子可能是一个大数的所有因子的集合——你可以有效地测试任何整数是否是一个因子,但不能有效地得到所有的因子。

可迭代

Category 的子类型是接口 Iterable。它表示您可以从中一次获取每个元素的类型,但不一定对元素进行索引。元素可能没有 well-defined 顺序。这些元素甚至可能还不存在,而是即时生成的。 collection 甚至可能无限长!它的正式成员是:

shared formal Iterator<Element> iterator()

一个例子是像标准输出这样的字符流。另一个例子是提供给 for 循环的整数范围,一次生成一个数字的内存效率更高。

这是 Ceylon 中的一种特殊类型,可以缩写为 {Element*}{Element+},具体取决于可迭代对象是否为空或绝对不为空。

Collection

Iterable 的一个子类型是接口 Collection。它有一个正式成员:

shared formal Collection<Element> clone()

但这并不重要。定义 Collection 的重要内容是文档中的这一行:

All Collections are required to support a well-defined notion of value equality, but the definition of equality depends upon the kind of collection.

基本上,Collection 是 collection,其结构 well-defined 足以彼此等同且可克隆。这种对 well-defined 结构的要求意味着这是最后一个超级抽象接口,其余的看起来更熟悉 collections.

列表

Collection 的子类型之一是接口 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)

顺序,顺序,空

List 的子类型中最重要的是接口 Sequential。它代表一个不可变的List。 Ceylon 喜欢这种类型并围绕它构建了许多语法。它被称为 [Element*]Element[]。它恰好有两个子类型:

  • Empty(又名[]),表示空collections
  • Sequence(又名[Element+]),表示非空collections.

因为 collection 是不可变的,所以您可以用它们做很多事情,而您不能用可变的 collection 做。其一,空列表上的 null 可能会导致许多操作失败,例如 reduce and first, but if you first test that the type is Sequence 那么您可以保证这些操作将始终成功,因为 collection 以后不会变空(它们是不可变的)毕竟)。

元组

Sequence 的一个非常特殊的子类型是 Tuple,这里列出的第一个真正的 class。与 Sequence 不同,其中所有元素都被限制为一种类型 ElementTuple 每个元素都有一个类型。它在 Ceylon 中有特殊的语法,其中 [String, Integer, String] 是一个不可变的列表,只包含三个元素,这些元素的类型完全按照那个顺序。

数组

List的另一个子类型是Array,也是一个真正的class。这是熟悉的 Java 数组,一个可变的 fixed-size 元素列表。

drhagen 已经很好地回答了你问题的第一部分,所以我只对第二部分说一点:你什么时候使用哪种类型?

通常:编写函数时,使其接受支持您需要的操作的最通用类型。到目前为止,很明显。

Category非常抽象,用处不大。

Iterable 如果您期望一些您将要迭代的元素流(或使用 filter 之类的流操作,则应使用, map, 等等).

关于 Iterable 的另一件事是它在命名参数中有一些额外的语法糖:

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 online

任何类型 Iterable 的参数都可以作为命名参数列表末尾的逗号分隔参数列表提供。也就是说,

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

相当于

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

这使您可以制作 DSL 风格的表达式; tour 有一些很好的例子。

CollectionCorrespondence 一样,相当抽象,根据我的经验很少直接使用。

List 听上去应该是经常用到的类型,其实我不记得用过多少了。我不知道为什么。我似乎跳过它并将我的参数声明为 IterableSequential.

SequentialSequence 是您想要不可变的固定长度列表的时候。它还有一些语法糖:像 void foo(String* bar) 这样的可变参数方法是 SequentialSequence 参数的快捷方式。 Sequential 还允许您使用 nonempty 运算符,它通常与 firstrest:

结合使用效果很好
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 online

当我要多次迭代流时,我通常使用 SequentialSequence(这对于通用 Iterable 来说可能很昂贵),尽管 List 可能是更好的界面。

Tuple 永远不应该用作 Tuple (除非在极少数情况下你对它们进行抽象),但是 [X, Y, Z] 语法糖,它通常很有用。您通常可以在子 class 中将 Sequential 成员细化为 Tuple,例如。 G。 superclass 有一个 <String|Integer>[] elements ,在一个 subclass 中已知是 [String, Integer] elements.

Array我从来没有用过作为参数类型,只是很少作为class来实例化和使用。