Pythonなら
from itertools import * N = 1000 print sum(ifilter(lambda n: n % 3 == 0 or n % 5 == 0, xrange(1, N)))
Haskellなら
n = 1000 main = print (sum (filter (\m -> mod m 3 == 0 || mod m 5 == 0) [1..n-1]))
こんな関数型で書くことを目標にしましょう。
Range
まず、Pythonのxrangeみたいなのはこう書きます。
println (1 to 10)
Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Rangeオブジェクトといって、xrangeと同じように最初と最後の値だけ持つみたいです。あと、刻み幅を指定するにはこうします。
println (1 to 10 by 3)
Range(1, 4, 7, 10)
sum
和を取るには、
println ((1 to 10).sum)
55
こうです。メソッドで引数を取らない場合は括弧は省略できます。
それより、sumはRangeオブジェクトのメソッドなんですね。いままで見てきた言語では、sumは前に書いていたから違和感があります。例えば、Pythonではsumは組込み関数で、要素に+演算子が定義されているiterableならなんでもいいんだっけかな?HaskellはPreludeの関数、C++はstd::accumulateでテンプレートの力でなんとかしています。そういうわけで違和感があるのですが、万事この調子なので頭を切り替えて語順を逆にしなければなりません。
filter
sumの次はfilterです。書く順は逆ですが。
def even(n :Int) = n % 2 == 0 println ((1 to 10).filter(even).sum)
30