2016-10-25 4 views
0

2つの数値の最大公約数を計算する次の関数を定義しました。"rec"が必要な理由

let rec gcd n m = if m = 0 then n else gcd m (n mod m);; 

キーワードrecなしでは機能しません。

私は不思議ですが、なぜ、recが必要なのですか?

gcdというスコープ内に他の機能はありません。したがって、コンパイラが何を呼び出す必要があるのか​​はっきりしています。

別の関数gcdが有効な場合でも、コンパイラは何らかの順序でマッチングを試み、Haskellのようなものを見ることができます。

これが有用な理由の例を挙げることができますか?

+0

'rec'は、TCOを実行することを示していますか?その場合、スカラの再帰的アノテーションのように、再帰を最適化できない場合に警告します。 – Carcigenicate

+0

@Carcigenicate:いいえ、recは任意の再帰関数定義に必要です。 – Marth

+1

[なぜOcaml/F#の関数がデフォルトで再帰的でないのですか?](http://stackoverflow.com/questions/900585/why-are-functions-in-ocaml-f-not-recursive-by-default ) – Marth

答えて

3

ほとんどの関数は非再帰型なので、デフォルトでは関数名はその本文には表示されません。また、機能を再定義するのに役立ちますこれは、あなたがname機能をモジュールUserがあると、あなたはあなたの新しいモジュールでそれを再定義したいと思います:(

module User = struct 
    type t = {name : string} 
    let name t = t.name 
end 

module RespectedUser = struct 
    include User 
    let name t = "Mr. "^name user 
end 

もしname名前何のための関数名の悪い選択例)が本体に表示される場合は、name関数を実装する方がはるかに難しくなります。それはより頻繁に道に立つでしょう、そして、それは実際に必要です。これは、誤って関数を再帰的に行うときに、既存の関数をオーバーロードしたがっているにもかかわらず、Haskellでプログラミングするときは常に問題です。

+1

HaskellもOCamlも多重定義をサポートしていません。 'name'の定義は古いものを置き換えます。 – sepp2k

+0

私は(これらの2つの単語を混乱させる)オーバーライドを意味しました。 OCamlは、メソッドが遅延バインディングを持つため、メソッドのオーバーロードをサポートしています。 – ivg

+1

オーバーロードは、同じ名前の2つの関数がありますが、異なる数または型の引数があり、コンパイラがどの引数を呼び出すかに基づいて適切な関数を呼び出す場合です。オーバーライドは、サブクラスがスーパータイプと同じシグネチャを持つメソッドを定義し、受信側のタイプに基づいて実行時に正しいバージョンが選択された場合です。OCamlは前者をサポートしていません。後者をサポートしています。あなたがしたことはどちらでもありません。 – sepp2k

関連する問題