新しいアカウントで始めました。

身の回りの出来事や写真が中心です。

F#イジってみました。Tourその15B RecursiveFunctions

2022-06-09 22:31:06 | F#

 F#も完全関数型ではないようですが、それに近い。最大公約数を求めるC言語の参考書から、アルゴリズムを頂いたのですが、C言語は変数を扱いますが、ほぼそれだけ、F#ではletで普通にやると、拘束される。変更できない。どうしてもということだとmutableと入れます。図のように。再帰の例のようにやろうとしたんですが、C言語のif文の解釈が違っていたようで、無限ループしてしまいましたので、除算の余りの方に変えました。


コメント (1)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« F#イジってみました。Tourそ... | トップ | VBイジってみました。Tourそ... »
最新の画像もっと見る

1 コメント

コメント日が  古い順  |   新しい順
mutableは必要ない (cametan_42)
2022-06-10 01:19:21
まず、factorialも末尾再帰させて、最適化しちまいましょう。
OCamlで書きますが、こんなカンジです。

let factorial n =
 let rec iter n acc = match n with
   0 -> acc
  | _ -> iter (n-1) (n * acc) in
 iter n 1;

例によってローカル関数を使ってますが、ビビらないように。
関数型言語ではローカル関数を使うのはフツーです。
手続き型言語でもPascalなんかはローカル関数が使えて、昔、「Pascalからプログラミング言語を学んだ」人にとってもフツーなんです。C言語を基礎、なんかにするからおかしくなる。

次。
greatestCommonFactorWhileは次のように書ける。mutableは必要ない。

let rec greatestCommonFactorWhile a b = match b with
 0 -> a
 | _ -> greatestCommonFactorWhile b (a mod b);;

そもそも、isamさんの提示してるコードを見る限り、まず、wwと言う変数の存在は値の一時退避用に存在してるだけです。aa に bbを代入するとaaが元々持ってた値が消えてしまう為、先にww = aa % bbを計算して保存、そしてあとでbbにwwを代入して帳尻を合わせている。
一方、末尾再帰で書けばそういうギミックは必要ない。スコープ内で参照出来る変数はそのまま参照可能なんで、一時退避させる無駄は必要ないんです。

そもそも、C言語でもこう書く事は一応可能です。

int greatestCommonFactorWhile(int a, int b) {
 if (b == 0) {
  return a;
 } else {
  return greatestCommonFactorWhile(b, a % b);
 }
}

これでも充分動きます(試してみて下さい)。
ただ、実装依存なんで信用しちゃあならない方式なんですけどね。一応、コンパイラによっては・・・例えばgccとかclangだと、最適化オプション -O2 等を付けてコンパイルすると末尾再帰最適化してくれて、効率的な実行ファイルを生成してくれます。
返信する

F#」カテゴリの最新記事