我一直在研究递归和TCO。似乎TCO可以使代码冗长并影响性能。例如我已经实现了代码,该代码接收7位数的电话号码并且返回所有可能的单词排列,例如464-7328可以是" GMGPDAS ... IMGREAT ... IOIRFCU"这是代码。
/*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&#39; ed。我必须花费相当多的时间,而且代码变得非常冗长。我不会为了节省空间而构成整个代码。 Here is a link to git repo link。可以肯定的是,相当多的人可以编写比我更好更简洁的尾递归代码。我仍然认为通常TCO更冗长(例如Factorial和Fibonacci尾调用递归有额外的参数,累加器。)然而,需要TCO来防止堆栈溢出。我想知道你将如何接近TCO和递归。在this thread中使用TCO实现Akermann的方案是我的问题陈述的缩影。
答案 0 :(得分:5)
你是否有可能使用术语“尾调用优化”,实际上你真的要么意味着以迭代递归方式编写函数,要么继续传递样式,以便所有递归调用都是尾调用? / p>
实施TCO是语言实施者的工作;一篇论文谈论如何有效地完成它是经典的Lambda: the Ultimate GOTO论文。
尾部调用优化是您的语言评估者将为您做的事情。另一方面,您的问题听起来像是在询问如何以特定样式表达函数,以便程序的形状允许评估者执行尾调用优化。
答案 1 :(得分:4)
正如评论中提到的sclv,尾递归对于Haskell中的这个例子来说毫无意义。使用list monad可以简洁有效地编写问题的简单实现。
import Data.Char
getChars n | n > 1 = [chr (ord 'a' + 3*(n-2)+i) | i <- [0..2]]
| otherwise = ""
getTelNum = mapM getChars
答案 2 :(得分:3)
正如其他人所说,我不会担心这种情况的尾调用,因为与输出的大小相比,它不会非常深入地(输入的长度)递归。在你出局之前你应该没有记忆(或耐心)
我可能会实现类似
的实现def getTelWords(input: List[Int]): List[String] = input match {
case Nil => List("")
case x :: xs => {
val heads = getChars(x)
val tails = getTelWords(xs)
for(c <- heads; cs <- tails) yield c + cs
}
}
如果你坚持尾递归,那可能是基于
def helper(reversedPrefixes: List[String], input: List[Int]): List[String]
= input match {
case Nil => reversedPrefixes.map(_.reverse)
case (x :: xs) => helper(
for(c <- getChars(x); rp <- reversedPrefixes) yield c + rp,
xs)
}
(实际例程应调用helper(List(""), input)
)