ES2015 の iterable/iterator/generator による無限 FizzBuzz (オブジェクト指向編)
ES2015 の iterable/iterator/generator による無限 FizzBuzz | tech - 氾濫原 に続いて、オブジェクト指向っぽく書けるようにしてみました。
ポイントはジェネレータ的なものをラップして常に It というクラスのインスタンスにするところです。
"use strict";
function It(iterable) { if (typeof this === 'undefined') return new It(iterable); this.iterable = iterable; }
It.countup = function* (n) {
for (;;) yield n++;
};
It.prototype = {
zip : function* () {
const iterators = [];
for (let it of this) {
iterators.push(it[Symbol.iterator]());
}
for (;;) {
const nexts = [];
for (let it of iterators) {
nexts.push(it.next());
}
yield nexts.map( (i) => i.value);
if (nexts.some( (i) => i.done) ) break;
}
},
map : function* (func) {
for (let value of this) {
yield func(value);
}
},
cycle : function* () {
for (;;) {
for (let value of this) {
yield value;
}
}
},
take : function (n) {
const ret = [];
for (let value of this) {
ret.push(value);
if (!(ret.length < n)) break;
}
return ret;
}
};
It.prototype[Symbol.iterator] = function () { return this.iterable[Symbol.iterator]() };
{
let wrapGenerator = function (generator) {
return function () {
const self = this;
const args = arguments;
const iterable = {};
iterable[Symbol.iterator] = function () {
return generator.apply(self, args);
}
return new It(iterable);
}
};
let generatorConstructor = Object.getPrototypeOf(function*(){}).constructor;
for (let key of Object.keys(It.prototype)) {
if (It.prototype[key] instanceof generatorConstructor) {
It.prototype[key] = wrapGenerator(It.prototype[key]);
}
}
}
console.log(Array.from(
It([
It.countup(1),
It(["", "", "Fizz"]).cycle(),
It(["", "", "", "", "Buzz"]).cycle()
]).
zip().
map( (_) => _[1] + _[2] || _[0] ).
take(30)
));
関連エントリー
- ES2015 の iterable/iterator/generator による無限 FizzBuzz ES2015 の iterable protocol / iterator protocol だとそこそこ自然に無限リストを作れるわけなので...
- Generator は iterator であり、iterable でもある 表題の通りですが、Generator にはいずれの protocol も実装されています。気になるのは iterable の挙動ですが、どう...
- Benchmark.js の結果表示を改善する Benchmark.js ちゃんと使えるので良いのですが、計測を頑張っている割に結果表示が貧弱というのが悲しいところです。 なので Perl...
- JS 数値リテラルに単位をつけたい [tech] デカい文字をA4で分割して印刷するツールをJSで書いた | Sat, Mar 7. 2015 - 氾濫原 では、実寸サイズを扱...
- textarea.value は代入すると値が変わる 以下のような挙動をする。 var textarea = document.createElement('textarea'); textar...