Fizz Buzz 再び
からトラックバックを頂いたこともあり、
改めてFizz Buzzを書いてみた・・・
シンプル版
これは上記リンク先のとほとんど同じだが、この場合"n match"の部分は省略できる。
(1 to 100).map { case n if (n%3 == 0) && (n%5 == 0) => "Fizz Buzz" case n if (n%3 == 0) => "Fizz" case n if (n%5 == 0) => "Buzz" case n => n.toString }
同じことを、for内包表記で書けば
for (n <- 1 to 100) yield n match { case n if (n%3 == 0) && (n%5 == 0) => "Fizz Buzz" case n if (n%3 == 0) => "Fizz" case n if (n%5 == 0) => "Buzz" case n => n.toString }
これは、内部的にも上と全く同じ
ちょっと改良して、DRYな感じにしてみた。
(1 to 100).map{ n => val b = new scala.collection.mutable.ArrayBuffer[String] if (n%3 == 0) b + "Fizz" if (n%5 == 0) b + "Buzz" if (b.isEmpty) n.toString else b.mkString(" ") }
ここで、ふと思い・・・
(1 to 100).map {n => val m3 = n % 3 == 0 val m5 = n % 5 == 0 n match { case n if (m3 && m5) => "Fizz Buzz" case n if (m3) => "Fizz" case n if (m5) => "Buzz" case n => n.toString } }
と
for { n <- 1 to 100 m3 = n % 3 == 0 m5 = n % 5 == 0 } yield n match { case n if (m3 && m5) => "Fizz Buzz" case n if (m3) => "Fizz" case n if (m5) => "Buzz" case n => n.toString }
を比較してみた。
Xprint:namerオプションをつかって確認したところ、
for内包表記バージョンは、内部的には以下と同じ模様。
mapが2回入っているので効率が悪い。
(1 to 100).map{n => val m3 = n % 3 == 0 val m5 = n % 5 == 0 (n, m3, m5) }.map{ case (n, m3, m5) => n match { case n if (m3 && m5) => "Fizz Buzz" case n if (m3) => "Fizz" case n if (m5) => "Buzz" case n => n.toString } }