Ответ 1
Я автор Immutable.js(и поклонник Lazy.js).
Используются ли Lazy.js и Immutable.js Seq с помощью короткого замыкания? Нет, не совсем. Но они удаляют промежуточное представление результатов операции.
Сокращенное слияние - это метод компиляции/транспиляции кода. Ваш пример хороший:
var a = [1,2,3,4,5].map(square).map(increment);
Transpiled:
var a = [1,2,3,4,5].map(compose(square, increment));
Lazy.js и Immutable.js не являются передатчиками и не будут переписывать код. Это библиотеки времени выполнения. Таким образом, вместо короткого слияния (техника компилятора) они используют итеративный состав (техника времени исполнения).
Вы ответите на это в своем TL;DR:
Насколько я знаю, они избавляются от промежуточных массивов, подражая ленивым оценка через объекты последовательности (например, итераторы). Однако, я считаю, что эти итераторы соединены цепью: один итератор, питающий свои значения лениво к следующему. Они не объединены в один итератор. следовательно они не "устраняют промежуточные представления". Они только преобразовывать массивы в объекты постоянной пространственной последовательности.
Это точно.
Пусть распаковывается:
Массивы сохраняют промежуточные результаты при цепочке:
var a = [1,2,3,4,5];
var b = a.map(square); // b: [1,4,6,8,10] created in O(n)
var c = b.map(increment); // c: [2,5,7,9,11] created in O(n)
Трансляция с коротким разрезом создает промежуточные функции:
var a = [1,2,3,4,5];
var f = compose(square, increment); // f: Function created in O(1)
var c = a.map(f); // c: [2,5,7,9,11] created in O(n)
Итерируемая композиция создает промежуточные итерации:
var a = [1,2,3,4,5];
var i = lazyMap(a, square); // i: Iterable created in O(1)
var j = lazyMap(i, increment); // j: Iterable created in O(1)
var c = Array.from(j); // c: [2,5,7,9,11] created in O(n)
Обратите внимание, что с использованием итеративной композиции мы не создали хранилище промежуточных результатов. Когда эти библиотеки говорят, что они не создают промежуточных представлений, что они означают, именно то, что описано в этом примере. Структура данных не создается, сохраняя значения [1,4,6,8,10]
.
Однако, конечно, выполняется некоторое промежуточное представление. Каждая "ленивая" операция должна что-то вернуть. Они возвращают итерабельность. Их создание чрезвычайно дешево и не связано с размером данных, которые используются. Обратите внимание, что при короткой транскрипции слияния также производится промежуточное представление. Результатом compose
является новая функция. Функциональный состав (рукописный или результат компилятора с коротким разрезом) очень связан с композицией Iterable.
Целью удаления промежуточных представлений является производительность, особенно в отношении памяти. Итерируемая композиция является мощным способом реализации этого и не требует накладных расходов, которые анализируют и переписывают код оптимизирующего компилятора, который был бы неуместен в библиотеке времени выполнения.
Appx:
Вот что может выглядеть простая реализация lazyMap
:
function lazyMap(iterable, mapper) {
return {
"@@iterator": function() {
var iterator = iterable["@@iterator"]();
return {
next: function() {
var step = iterator.next();
return step.done ? step : { done: false, value: mapper(step.value) }
}
};
}
};
}