递归是否有用?

时间:2017-05-24 20:18:18

标签: loops recursion tail-recursion

我最近了解到了尾递归作为一种方法,当你给它一个太大的数字来进行递归时,它不会崩溃。我意识到我可以轻松地将尾递归重写为while循环,并且它基本上完全相同,这让我感到疑惑 - 当你可以用正常循环做任何事情时,是否有任何递归用途?

是的,递归代码看起来更小并且更容易理解,但它也有可能完全崩溃,而一个简单的循环不会崩溃执行相同的任务。

2 个答案:

答案 0 :(得分:0)

我将以Haskell language为例,纯功能

  

Haskell中的每个函数都是数学意义上的函数   (即"纯")。即使是副作用的IO操作也只是一个   纯代码生成的描述。没有   语句或指令,只有不能改变的表达式   变量(本地或全局)或访问状态,如时间或随机   号。

因此,在haskell中,递归函数是尾递归的,如果最终的结果 递归调用是函数本身的最终结果。如果 必须进一步处理递归调用的结果(例如,通过添加 它是1,或者将另一个元素放在它的开头),它是 不是尾递归。 (see here

另一方面,在许多编程语言中,调用函数使用堆栈空间,因此尾递归函数可以构建一大堆对自身的调用,这会浪费内存。由于在尾调用中,包含函数即将返回,实际上可以丢弃其环境,并且可以在不创建新堆栈帧的情况下输入递归调用。这个技巧称为尾调用消除或尾调用优化,允许尾递归函数无限重复。

答案 1 :(得分:0)

距离我发布这个问题已经有很长时间了,我对该主题的看法已经改变。原因如下:

我学到了Haskell,这是一门解决递归问题的语言-递归定义和算法被转换为普通的循环算法,并且在大多数情况下,您甚至不直接使用递归,而是使用mapfoldfilter或它们的组合。在清除了所有不良问题之后,函数式编程的优点开始显现出来-一切都接近其数学定义,而不会被笨拙的循环和变量所遮盖。

对于要努力理解递归为什么很棒的其他人,请学习Haskell。它具有许多其他非常有趣的功能,例如:懒惰(仅在请求值时才评估值),静态(永远不能修改变量),纯净(函数除了输入和返回输出外不能执行其他任何操作,因此不进行打印)到控制台),使用非常有表现力的类型系统进行强类型键入,其中充斥着令人赞叹的抽象概念,例如Functor,Monad,State等。我几乎可以说这改变了生活。