Зачем вам создавать 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()
не нужно материализовать последовательность.