Небольшой этюд на тему работы c объектами, реализующими протоколы iterable и iterator, принятые стандартом ECMAScript 6 (он же 2015). Попробуем реализовать "горячий" и "ленивый" варианты итерируемой коллекции, с итераторами (само собой), генераторами, символами (куда же без них) и прочими свистелками (нововведениями стандарта), а также добавим "немного экстрима" в финале, не пытайтесь повторить это дома :).
"Горячий" вариант:
"Ленивый" вариант:
"Немного экстрима":
... или с помощью генератора:
Вот как-то так.
"Горячий" вариант:
var Eager = { map(fn) { var self = this; return Array.from( (function* () { for (var n of self) { yield fn(n); } })() ); }, filter(fn) { var self = this; return Array.from( (function* () { for (var n of self) { if (fn(n)) yield n; } })() ); }, take(num) { var self = this; return Array.from( (function* () { for (var n of self) { if (--num < 0) break; yield n; } })() ); }, toArray() { return Array.from(this); } }; var digits = Object.assign({ [Symbol.iterator]: () => { var n = 9, done; return { next: function() { done = done || n === 0; return { done, value: done ? undefined : n-- }; } }; } }, Eager);
"Ленивый" вариант:
var Lazy = { map(fn) { return Object.assign({ [Symbol.iterator]: () => { var iterator = this[Symbol.iterator](); return { next: () => { var it = iterator.next(), done = it.done; return { done, value: done ? undefined : fn(it.value) }; } } } }, Lazy); }, filter(fn) { return Object.assign({ [Symbol.iterator]: () => { var iterator = this[Symbol.iterator](); return { next: () => { var it, done, value; do { it = iterator.next(), done = it.done, value = it.value; } while (!done && !fn(value)); return { done, value }; } } } }, Lazy) }, take(num) { return Object.assign({ [Symbol.iterator]: () => { var iterator = this[Symbol.iterator](); return { next: () => { var it = iterator.next(), done = it.done || --num < 0; return { done, value: done ? undefined : it.value }; } } } }, Lazy); }, toArray() { return Array.from(this); } }; var digits = Object.assign({ [Symbol.iterator]: () => { var n = 9, done; return { next: function() { done = done || n === 0; return { done, value: done ? undefined : n-- }; } }; } }, Lazy);
"Немного экстрима":
var numbers = Object.assign({ [Symbol.iterator]: () => { var n = 0, done = false; return { next: function() { return { done, value: ++n }; } }; } }, Lazy);
... или с помощью генератора:
var numbers = Object.assign({ [Symbol.iterator]: function*() { var n = 0; while (true) { yield ++n; } } }, Lazy);
Вот как-то так.
Комментариев нет:
Отправить комментарий
Комментарий будет опубликован после модерации