特徴的な繰り返し処理 loop

多くの関数型プログラミングでは、繰り返し処理を関数の再帰呼び出しで表現することが好まれる傾向があります。

Phelの繰り返し処理において、高機能で便利に使える `for` マクロがありますが、よりプリミティブなループ処理を行なう `loop` 特殊形式があります。

https://phel-lang.org/documentation/control-flow/#loop

Phel の loop は、まるで再帰関数のように繰り返し処理を記述することが可能です。

(loop [sum 0

cnt 10]

(if (= cnt 0)

sum

(recur (+ cnt sum) (dec cnt))))

=> 55

同じ機能を再帰関数で記述した時は以下のようになります。

(defn my-sum-to-n [sum cnt]

(if (= cnt 0)

sum

(my-sum-to-n (+ cnt sum) (dec cnt))))

(my-sum-to-n 0 10)

=> 55

`loop`形式と再帰関数形式で異なる点があります。再帰として呼び出す際に、`loop`形式は`recur`を指定していますが、再帰関数形式では自身の関数名`my-sum-to-n`を指定しています。それ以外については、`loop`を使うことで、再帰関数を記述するのと同じように繰り返し処理を記述できるということがわかります。

ただし、もう一点注意すべき点があります。`loop`の再帰構造が、末尾再帰である必要があります。`loop`内の繰り返し処理の中で、最後に評価される場所にしか、`recur`を配置できないということになります。もし、それ以外の場所に`recur`を配置しようとした時は、以下のエラーが表示されます。

ERROR: Can't call 'recur here

このエラーが表示された場合は、`loop`の再帰構造が、末尾再帰になっているかを確認してください。