2016-12-28 12 views
3

次のように与えられます。 Object.keysから返された繰り返し可能な要素のそれぞれに、transformをゆっくりと適用したいと思います。合成ジェネレータ

どうすればいいですか?

function* numbers(upto, transform) { 
    yield* Object.keys([...Array(upto)]); // How can `transform` be applied here lazily? 
} 

function timesTwo(n) { 
    return n*2; 
} 

var generator = numbers(31, timesTwo) 

for(var i of generator) { 
    console.log(i); // 0 2 4 6 8... 60 
} 
+0

を必要とするだろうそれらを外部で構成するのではなく、「数値」に渡したのは正しいのですか? –

+0

はい。簡単な例を作成しようとしていましたが、何かが欠けていた可能性があります。 – Ben

+1

この分野の私の理解を発展させる...IIUC 'yield *'は内側の 'iterable'の各値が返されることを意味します。これは、私が理解できる限り、単純な例に当てはまります。私は実際の例がメモリに収まらない大きすぎる数字のリストかもしれないと思います。 – Ben

答えて

4

あなたはnumbersに渡さ変換持って幸せだので、あなたは発電機であることnumbersを利用する場合は、生成として、あなたはそれを適用することができます。

function* numbers(upto, transform) { 
 
    let n = 0; 
 
    while (n < upto) { 
 
     yield transform(n); 
 
     ++n; 
 
    } 
 
} 
 

 
const timesTwo = n => n * 2; 
 

 
const generator = numbers(31, timesTwo); 
 

 
for (const i of generator) { 
 
    console.log(i); // 0 2 4 6 8... 60 
 
}

ブラウザが上記を実行しないブラウザの場合はLive on Babel's REPLとなります。


我々はnumbersのあなたの元の定義を使用することができますが、私たちは熱心に代わりのなまけ変換を適用する必要があるだろうか、私たちは(配列がすべて作成されます配列の反復子を使用する必要があると思います一度に関係なく)。ここでは後者の一つです:

function* numbers(upto, transform) { 
 
    for (const n of Object.keys([...Array(upto)])) { 
 
    yield transform(n); 
 
    } 
 
} 
 

 
const timesTwo = n => n * 2; 
 

 
const generator = numbers(31, timesTwo); 
 

 
for (const i of generator) { 
 
    console.log(i); // 0 2 4 6 8... 60 
 
}

Live on Babel's REPL


我々はそこnumbersの二つの側面を分離し、基本的にmapの発電機のバージョンである汎用transform機能を持つことができます:

function* transform(iterable, f) { 
    for (const v of iterable) { 
    yield f(v); 
    } 
} 

その後、我々はより基本的にそれを使用することができますnumbers

function* transform(iterable, f) { 
 
    for (const v of iterable) { 
 
    yield f(v); 
 
    } 
 
} 
 

 
function* numbers(upto) { 
 
    yield* Object.keys([...Array(upto)]); 
 
} 
 

 
const timesTwo = n => n * 2; 
 

 
const generator = transform(numbers(31), timesTwo); 
 

 
for (const i of generator) { 
 
    console.log(i); // 0 2 4 6 8... 60 
 
}

On Babel's REPL


サイドノート:私はあなたがこれを知っている確信しているが、任意の潜伏者は、問題のnumbers [以下、これらのカップル]について一連の文字列を反復処理"0""1"などです。しかし、それらを乗算すると、数値に強制されます。実際には、質問者のnumbersアプローチに基づいた一連の番号を持っているために、我々は `transform`パラメータを使用すると、変換持って満足しているように、それが思われてしまうこと

yield* Object.keys([...Array(upto)]).map(Number)); 
+0

おそらく私が怠け者私は変換が遅れて実行される新しいiterableを構築する必要があります。 – Ben

+0

@BenAston:まさに。それは私が上記の2番目の例で行ったことです。次に、今戻って3番目に分離しました。 –

0

function lazy(f) { 
 
    return function*(iter) { 
 
     for(const v of iter) { 
 
      yield f(v); 
 
     } 
 
    } 
 
} 
 

 
function* numbers(upto, transform) { 
 
    yield* lazy(transform)(Object.keys([...Array(upto)])); 
 
} 
 

 
function timesTwo(n) { 
 
    console.log('times two called on ', n); 
 
    return n*2; 
 
} 
 

 
var generator = numbers(11, timesTwo) 
 

 
for(var i of generator) { 
 
    console.log(i); // 0 2 4 6 8... 20 
 
}

関連する問題