0, 1, … , 100までの数字の和を求める

while

var i = 0
var sum = 0
while(i <= 100) {
	sum += i
	i += 1
}

2つのvarが登場しているため不安が残る。少し安全に書くには以下のように関数内に処理を閉じ込めると良い。

def aseries(limit:Int) = {
	var i = 0
	var sum = 0
	while(i <= limit) { 
		sum += i 
		i += 1
	} 
	sum
}
aseries(100)

recursion 再帰を使う

関数の中で関数を定義しScalaらしいコードに。

def aseries(limit:Int) = {
   def loop(i:Int) : Int = if(i <= limit) i + loop(i+1) else i
   loop(0)
}
aseries(100)

このような形の再帰は末尾再帰と呼ばれ、Scalaコンパイラは自動的にwhile文を使った式に最適化してくれる。本当に末尾最適化されているか確認するためには、@tailrecアノテーションをつけておくこと。末尾再帰最適化できない場合コンパイルエラーになる。

@tailrec
def aseries(limit:Int) = {
   def loop(i:Int) : Int = if(i <= limit) i + loop(i+1) else i
   loop(0)
}
aseries(100)

for loop

for loopはおなじみ。

var sum = 0
for(i <- 0 to 100)
	sum += i

より短く,

var sum = 0
(0 to 100) foreach (sum += _)

varの使用を避けてより関数型言語らしく

(0 to 100) reduce (_ + _)
(0 to 100) fold(0)(_ + _)  // 初期値を明示したい場合
comments powered by Disqus