1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript:しょうこりもなくFizzBuzz。 からの無限ジェネレータからの takeとか mapとか forEachっぽいものとか

Last updated at Posted at 2018-03-02

JavaScript リファレンスで調べつつ、最近の書き方でやってみた。

const fizzBuzz = x => 
    x % 3 === 0 && x % 5 === 0 ? "FizzBuzz"
  : x % 3 === 0 ?  "Fizz"
  : x % 5 === 0 ?  "Buzz"
  : x
;

[...Array(100).keys()]
  .forEach( e => console.log( fizzBuzz( e+1 ) ) )

効率とかは考えずに取り敢えず見た目でやってます。

  • 三項演算子のネスト?好きかも。ガードっぽく見えてくる。
  • 区切りがわからなくなるらしい。;が要る。
  • [...Array(100).keys()][0, 1, 2...98, 99] ってことらしい。for文ぽいものを脳内で変換するとき便利かも。
  • .forEach()に登録する関数は要素、添字、配列の順で引数をとるらしい。この場合は要素eのみ。全部入りなら (e, i, arr) => console.log( fizzBuzz( e+1 )) みたいに書く。引数にかっこが要る。

いっそこれでいいのかな?わかりやすい。※以下、fizzBuzz() は共通なので省略

[...Array(100)]
  .map( (e, i) => fizzBuzz( i+1 ) )
  .forEach( e => console.log( e ) )

配列は繰り返しのための添字だけあればいいし、表示したらもう使わないので

[...Array(100)]
  .forEach( (e, i) => console.log(fizzBuzz( i+1 )) )

いったん戻ってfor文。これはわかる

for(let i = 0; i < 100; i++ ){
  console.log( fizzBuzz( i+1 ) );
}

ジェネレータでrange関数を作って使う

function* range(n){
    for(let i = 0; i < n; i++) yield i;
}

for(const i of range(100)){
  console.log( fizzBuzz( i+1 ) );
}

こんなこともできるのか。いいかどうかは謎。

function* range(n){
    for(let i = 0; i < n; i++) yield i;
}

[...range(100)]
  .forEach( e => console.log( fizzBuzz( e+1 ) ) )

ならこれは?
ひたすら関数をかけ続けるジェネレータ nest と、ジェネレータから有限個だけ取り出す take を定義して

function* nest(f, x){
  let y=x;
  while(true){
    yield y
    y=f(y)
  }
}
const unlimitedRange = nest( n => n+1, 0 )

function* take(n,g){
  for(let i=0; i<n; i++)yield g.next().value
}

[...take(100, unlimitedRange ) ]
  .map( e => fizzBuzz( e+1 ) )
  .forEach( e => console.log( e ) )

いけるんだ...
じゃあこれ。ジェネレータを引数にして関数 f を適用しつづけるジェネレータ mapG をプラスして...

function* take( n, g ) { for(let i=0; i<n; i++) yield g.next().value }
function* mapG( f, g ) { while(true) yield f( g.next().value ) }
function* nest( f, x ) {
  let y=x
  while( true ) {
    yield y
    y = f( y )
  }
}

[...take( 100, mapG( fizzBuzz, nest( n=> n+1, 1) ) ) ]
  .forEach( e => console.log( e ) )

mapがなくなり、これはこれですっきり。
どうせなら.forEach もなくしちゃお。何もせず、副作用だけ起こすジェネレータ attach を作って、

function* take( n, g ) { for( let i=0; i<n; i++ ) yield g.next().value }
function* mapG( f, g ) { while( true ) yield f( g.next().value ) }
function* nest( f, x ){
  let y=x
  while( true ) {
    yield y
    y = f( y )
  }
}
function* attach(f, g) {
  let x
  while(true){
    f(x = g.next().value)
    yield x
  }
}
[...take( 100, attach(console.log, mapG( fizzBuzz, nest( n=> n+1, 1) ) ) ) ]

わーい。forEachもなくなって一行になったー。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?