ライブラリ関数と定義した関数の差異
現状の実装では、アロー関数で `return` を省略した場合の返却値について、ライブラリ関数と JavaScript で書いた関数の扱いに、微妙な差異が生じているようです。
例です。よくある、配列から最大値を探す処理をアロー関数で書きました。
[ 1, 5, 3, 8, 6 ].reduce((x, y) => Math.max(x, y), -Infinity);
返却値は `8` です。正しく動いています。
ふと気付きます。普通の関数型言語では、こういう場合、アロー関数なしで機能するはず…。
[ 1, 5, 3, 8, 6 ].reduce(Math.max, -Infinity);
返却値は `NaN` です。あれ? だめなんかい…。おそらく `Math.max` が計算結果ではなく `undefined` を返しているのでしょう。
さらに閃きます。`max` を自前で書いたらどうなる?
const max = (x, y) => x > y ? x : y;
[ 1, 5, 3, 8, 6 ].reduce(max, -Infinity);
返却値は `8` です。関数の型(`Number * Number -> Number`)としては同じだと思いますが、ライブラリ関数は NG で、自前で書いたものは OK ですね…。
なお、reduce を自前で書いてもうまくいきます。
function reduce (array, fn, initial) {
let r = initial;
for (let i = 0; i < array.length; i++) {
r = fn(r, array[i]);
}
return r;
}
reduce([ 1, 5, 3, 8, 6 ], Math.max, -Infinity);
ES6 非サポートの環境でも同様の結果になります。どうも昔からあるバグのように見えます。