rubyでinjectを使って自乗和を計算しようとしたら計算結果がずれていたので、少し原因を調査した。
非常に簡単な理由だったが、一応備忘録として残しておく。
原因
injectで初期値を指定した場合と指定しなかった場合でレシーバの走査方法が異なる
検証
2〜5の自乗和を求める
# 初期値を指定した場合
(2..5).inject(0) { |res, i| res + i**2 }
=> 54
# 初期値を指定しなかった場合
(2..5).inject { |res, i| res + i**2 }
# => 52
計算結果として正しいのは「初期値を指定した」場合である。
2 ^ 2 = 4
3 ^ 2 = 9
4 ^ 2 = 16
5 ^ 2 = 25
4+9+16+25=54
ここでinjectの定義を確認すると、「初期値 init を省略した場合は、最初に先頭の要素と 2 番目の要素をブロックに渡します」とある。
これを踏まえて、上記のケースについて計算過程の詳細を確認してみる。
# 初期値を指定した場合
1回目
res=0 i=2
0+2^2=4
2回目
res=4 i=3
4+3^2=13
3回目
res=13 i=4
13+4^2=29
4回目
res=29 i=5
29+5^2=54
# 初期値を指定しなかった場合
1回目
res=2 i=3
2+3^2=11
2回目
res=11 i=4
11+4^2=27
3回目
res=27 i=5
27+5^2=52
ということで、計算結果が一致した。
まとめ
自分が使おうとするメソッドの挙動を把握しておこう