Я прочитал пошаговое руководство по последовательностям, но не совсем понимаю, почему есть способ определить как буквальный Iterable, так и буквальный Sequence.
{String+} iterable = {"String1", "String2"};
[String+] sequence = ["String1", "String2"];
Поскольку Sequence является подтипом Iterable, кажется, что он должен уметь делать все, что делает 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()
и {{X3} } возвращает поток. И даже printAll()
не нужно материализовать последовательность.
Похожие вопросы
Новые вопросы
ceylon
Цейлонский язык программирования для виртуальных машин Java и JavaScript.