私は再帰と TCO を調べてきました。TCO はコードを冗長にし、パフォーマンスにも影響を与える可能性があるようです。たとえば、7 桁の電話番号を取り、可能なすべての単語の順列を返すコードを実装しました。
/*Generate the alphabet table*/
val alphabet = (for (ch <- 'a' to 'z') yield ch.toString).toList
/*Given the number, return the possible alphabet List of String(Instead of Char for convenience)*/
def getChars(num : Int) : List[String] = {
if (num > 1) return List[String](alphabet((num - 2) * 3), alphabet((num - 2) * 3 + 1), alphabet((num - 2) * 3 + 2))
List[String](num.toString)
}
/*Recursion without TCO*/
def getTelWords(input : List[Int]) : List[String] = {
if (input.length == 1) return getChars(input.head)
getChars(input.head).foldLeft(List[String]()) {
(l, ch) => getTelWords(input.tail).foldLeft(List[String]()) { (ll, x) => ch + x :: ll } ++ l
}
}
短いので、あまり時間を割く必要はありません。ただし、TCO を取得するために末尾呼び出しの再帰でそれを実行しようとすると。かなりの時間を費やす必要があり、コードが非常に冗長になります。スペースを節約するためにコード全体をポーズするつもりはありません。これは git repo link へのリンクです。多くの皆さんが、私よりも優れた簡潔な末尾再帰コードを作成できることは確かです。一般に、TCO はより冗長であると私は今でも信じています (たとえば、階乗およびフィボナッチの末尾呼び出し再帰には、アキュムレータという追加のパラメーターがあります)。しかし、TCO はスタック オーバーフローを防ぐために必要です。TCO と再帰にどのようにアプローチするかを知りたいです。このスレッドでの TCO を使用した Akermann の Scheme 実装は、私の問題点の典型です。