繰り返し処理と再帰(C,Java,python,Clojure)
繰り返し機能は、プログラミング言語の中でも基本機能で、プログラミング言語の歴史でも述べた構造化言語の3つの機能である(1)順次進行、(2)条件分岐、(3)繰り返しの中の一つの要素となる。
これは例えばC言語では以下のように表される。
int main()
{
int i;
for(i = 0; i < 3; i++){
printf("%d ", i);
}
printf("\n");
return 0;
}
またJavaでは以下のようになり
class Test{
public static void main(String args[]){
for(int i = 0; i < 3; i++)
System.out.printf("%d ",i);
System.out.printf("\n");
}
}
Javascriptでは以下のようになる。
putstr(i + " ");
}
print("")
for(var i = 1; i < 10; i+=2){ /*増分(ステップ)=2*/
putstr(i + " ");
}
print("")
pythonではかなりシンプルな形となる。
for i in range(0,3):
print i,
print
Clojureではシーケンスを続ける形の表現となり以下のようになる。
(doseq [i (range 0 3)]
(println i))
コードの短さと直感的な理解のしやすさでは、後者の2つ(python,Clojure)が改善されている。
ここでClojureでは「doseq」以外の繰り返しとして、for 、loop〜recur、map、reduce等がある。
まず一番シンプルで多用されるものとして以下のようなmapがある。
(map + [1 2 3] [4 5 6])
;;=> (5 7 9)
mapは関数(上記の場合は「+」)をそれぞれのベクトル(あるいはマップデータ等)に対して、順に適用させていく形となる。これらを総当たりで適用させたい場合は以下のようにforを用いる。
(def digits [1 2 3])
(for [x1 digits
x2 digits]
(* x1 x2))
;;=> (1 2 3 2 4 6 3 6 9)
また、loop〜recurは再帰的な構文に利用され最もシンプルな形だと以下のように表される。
(loop [x 10 ;;カウント初期値
sv. f(0)]
(when (> x 1)
(println x)
(do (println x). ;; デバッグ用のデータ出力
(recur (- x 2)(f sv x))))
上記はある変数xに対して、recurで末尾再帰する関数となっており、ある条件(x>1)となったところでループから脱出する。recurの変数はloopで定義されたものが全て現れる必要があり、内部で起こっている状態を監視(デバッグ)するため、recurとデバッグ関数をdoでラップする。ここでf(x)=svという変数が再帰的に変化していく。
mapに関しては、高階関数(関数を評価する関数)というものになり、関数型言語の特徴となる使い方をされる。それら高階関数に関しては、別途述べたいと思う。
コメント
[…] 繰り返し処理と再帰 C,Java,Javascript,Pythonとの比較とmap,looprecur […]
[…] 繰り返し処理と再帰(C,Java,JavaScript,Clojure) […]
[…] 繰り返し処理と再帰(C,Java,JavaScript,Clojure) […]