F#も完全関数型ではないようですが、それに近い。最大公約数を求めるC言語の参考書から、アルゴリズムを頂いたのですが、C言語は変数を扱いますが、ほぼそれだけ、F#ではletで普通にやると、拘束される。変更できない。どうしてもということだとmutableと入れます。図のように。再帰の例のようにやろうとしたんですが、C言語のif文の解釈が違っていたようで、無限ループしてしまいましたので、除算の余りの方に変えました。
最新の画像[もっと見る]
「F#」カテゴリの最新記事
- F#イジってみました。Functionsその15。composeで関数を合成する
- F#イジってみてました。Functionsその14。高階関数ですよね。>カリー化
- F#イジってみてました。Function13高階関数、カリー化
- F#イジってみてました。Functionsその12。高階関数、
- F#イジってみてました。Functionsその11。applyとは?
- F#イジってみてました。Functionsその10。関数定義の仮引数。
- F#イジってみてました。関数の復習を兼ねて…。前回と同じテーマ。
- F#イジってみました。Listの復習を兼ねて
- F#イジってました。moduleとは何でしょうか?
- F#イジってみました。VSCodeでF#デバッグできるか?Windows10です。
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 等を付けてコンパイルすると末尾再帰最適化してくれて、効率的な実行ファイルを生成してくれます。