1 / 16

Generator Composition in ES6

Generator Composition in ES6. Problem. Generators cannot abstract over sync IO. Two Ways to Iterate. var nums = function*() { yield 1; yield 2; }. Iterable. function Iterable ( generatorFunction ) { this[@@iterator] = generatorFunction ; };. Creating Iterables.

lassie
Télécharger la présentation

Generator Composition in ES6

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Generator Composition in ES6

  2. Problem Generators cannot abstract over sync IO.

  3. Two Ways to Iterate varnums = function*() { yield 1; yield 2; }

  4. Iterable function Iterable(generatorFunction) { this[@@iterator] = generatorFunction; };

  5. Creating Iterables let nums = new Iterable(function*() { yield 1; yield 2; yield 3; });

  6. Iterating Iterables for(let x of nums()) { console.log(x); } …becomes… let iterator = nums()[@@iterator], pair; while(!(pair = iterator.next()).done) { console.log(pair.value); }

  7. IO Streams as Iterables function getLines(fileName) { return new Iterable(function*() { let reader = new SyncReader(fileName); try { while(!reader.eof) { yield reader.readLine(); } } finally { reader.close(); } }) };

  8. Iterable Composition Iterable.prototype.map = function(projection) { let self = this; return new Iterable(function*() { for(let x of self) { yield projection(x); } }); }

  9. Iterable Composition (cont) Iterable.prototype.takeWhile = function(predicate) { let self = this; return new Iterable(function*() { for(let x of self) { if (!predicate(x)) { break; } yield x; } }); }

  10. Historical Stock Ticker Visualizer Symbol filter GOOG Date filter

  11. Created Filtered Iterable // massiveFileOfStockTickerHistory.txt // {date: 7347832748932, symbol: “BAC”, price: 16.62 }\n // {date: 7347832748939, symbol: “CTI”, price: 3.48 }\n let records = getLines(“massiveFileOfStockTickerHistory.txt”). map(line => JSON.parse(line)). filter(({symbol}) => symbol === selectedSymbol). skipWhile(({date}) => date > dateFrom). takeWhile(({date}) => date < dateTo); render(records); Lazy evaluation. Nothing has happened.

  12. Render Iterates Data function renderGraph(stocks) { // large file is opened. for(let stock of stocks) { // rendering } } Is file handle closed?

  13. takeWhile Leaks! Iterable.prototype.takeWhile = function(predicate) { return new Iterable(function*() { for(let x of this) { if (!predicate(x)) { break; } yield x; } }); }; function getLines(fileName) { return new Iterable(function*() { let reader = new SyncReader(fileName); try { while(!reader.eof) { yield reader.readLine(); } } finally { reader.close(); } }) }; Suspends Never executes!

  14. Can not Safely Page Generators! • Leak exposed by any operator that short-circuits… • take • takeWhile • Must iterate to completion to avoid leak • for…of useless over Generators that abstract over expensive resources

  15. Proposal • for…of always assumes generator creation • for…of always terminates generator function

  16. Rationale • For…of creates iterator • User-land cannot invoke iterator.return(), because iterator transparently created by for…of • “If you built it, you bought it.”

More Related