クラスで、再帰呼び出しの後にブール演算子が評価されるため、次の関数は末尾再帰ではないと言われました。
let rec exists p = function
[] -> false
| a::l -> p a || exists p l
しかし、これは1,000万サイズのリストのスタックを爆破するものではなく、さらに、標準ライブラリでの実装です。末尾再帰でなければ、一見同等で明らかに末尾再帰の代わりにこのフォームを使用する理由はありません。
let rec exists p = function
[] -> false
| a::l -> if p a then true else exists p l
したがって、OCamlコンパイラは、このような単純なケースでブール演算を最適化して、末尾再帰を利用できるようです。しかし、私がそのようにオペランドの順序を切り替えると、私は気づきました
let rec exists p = function
[] -> false
| a::l -> exists p l || p a
その後、スタックは実際に10mの要素に吹き飛ばされます。したがって、OCamlは、再帰呼び出しが右側に表示されている場合にのみこれを利用できるように見えます。これにより、コンパイラが行うのは、ブール値のopを同等の式に置き換えることだけであると思われますif
。誰かがこれを確認または反論できますか?