Зачем вам создавать Iterable вместо последовательности в Цейлоне?

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

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

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

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

2 ответа

Решение

Потоки ленивы.

import ceylon.math.float {random}

value rng = {random()}.cycled;

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

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

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

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

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

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

Другие вопросы по тегам