Я прочитал пошаговое руководство по последовательностям, но не совсем понимаю, почему есть способ определить как буквальный Iterable, так и буквальный Sequence.

{String+} iterable = {"String1", "String2"};
[String+] sequence = ["String1", "String2"];

Поскольку Sequence является подтипом Iterable, кажется, что он должен уметь делать все, что делает Iterable, и даже больше.

Зачем тогда нужен инициализатор Iterable фигурных скобок? Когда вы захотите использовать его вместо версии Sequence с квадратными скобками?

5
KPD 1 Мар 2015 в 05:27

2 ответа

Лучший ответ

Стримы ленивы.

import ceylon.math.float {random}

value rng = {random()}.cycled;

Итак, это ленивый бесконечный поток случайных чисел. Функция random не вызывается при построении потока. С другой стороны, последовательность будет нетерпеливо оценивать свои аргументы, в этом случае давая вам результат однократного вызова random снова и снова. Другой пример:

function prepend<Element>(Element first, {Element*} rest) => {first, *rest};

Здесь поток rest распределяется по результирующему потоку, но только по запросу.

7
gdejohn 1 Мар 2015 в 03:19

В точности то, что сказал @gdejohn, но я хочу отметить, что лень особенно важна для производительности , если вы собираетесь применить к потоку несколько операций, например:

value stream = { random() }.cycled
        .filter((x) => x>0.5)
        .map((x) => (x*100).integer);
printAll(stream.take(1000));

Здесь мы избегаем когда-либо материализации всей последовательности длиной 1000, поскольку каждая из промежуточных операций: cycled, filter(), map() и {{X3} } возвращает поток. И даже printAll() не нужно материализовать последовательность.

5
Gavin King 1 Мар 2015 в 10:39