Recursion 为什么OCaml中的递归比C++;还是Java?
caml.inria.fr网站上的这篇文章说Recursion 为什么OCaml中的递归比C++;还是Java?,recursion,ocaml,Recursion,Ocaml,caml.inria.fr网站上的这篇文章说 与C++和java相反,O-CAML[SiC]中的递归与迭代< /P>一样有效。 对于阶乘之类的东西,使用可变变量的循环似乎比递归调用涉及的堆栈操作更有效 C++语言的函数编程结构是否能使编译器更容易识别和优化递归? 见: 如果您以递归方式而不是迭代方式编写代码,那么在大型输入上必然会耗尽堆栈空间,对吗? 事实上,这是错误的。编译器可以对某些类型的递归函数执行简单的优化,将它们转换为while循环 我建议: OCaml的编译器将尾部递归优化为迭代结
与C++和java相反,O-CAML[SiC]中的递归与迭代< /P>一样有效。 对于阶乘之类的东西,使用可变变量的循环似乎比递归调用涉及的堆栈操作更有效
如果您以递归方式而不是迭代方式编写代码,那么在大型输入上必然会耗尽堆栈空间,对吗?
事实上,这是错误的。编译器可以对某些类型的递归函数执行简单的优化,将它们转换为while循环
我建议:
我不确定C++,它将取决于你使用的编译器。
< P>语言的函数编程结构可能使编译器更容易识别和优化递归。 见:如果您以递归方式而不是迭代方式编写代码,那么在大型输入上必然会耗尽堆栈空间,对吗?
事实上,这是错误的。编译器可以对某些类型的递归函数执行简单的优化,将它们转换为while循环
我建议:
我不确定C++,它将取决于你使用的编译器。
< P>是的,在某些情况下。这叫做尾部调用优化。以以下C-ish阶乘函数为例:int factorial(int n)
{
if (n < = 1)
return 1;
else
return n * factorial(n – 1);
}
当然,可以多次调用此函数,而不会使堆栈溢出(即使会很快使32位int溢出)。实际上,可以用OCaml编写同义函数。现在,OCaml的版本将再次使用递归。但是,如果我们在第一个函数中添加一个“累加器”参数,它可以重新编写为:
let factorial acc n = if n <= 1 then acc else factorial (acc * n) (n – 1)
让阶乘acc n=如果n是,在某些情况下。这叫做尾部调用优化。以以下C-ish阶乘函数为例:
int factorial(int n)
{
if (n < = 1)
return 1;
else
return n * factorial(n – 1);
}
当然,可以多次调用此函数,而不会使堆栈溢出(即使会很快使32位int溢出)。实际上,可以用OCaml编写同义函数。现在,OCaml的版本将再次使用递归。但是,如果我们在第一个函数中添加一个“累加器”参数,它可以重新编写为:
let factorial acc n = if n <= 1 then acc else factorial (acc * n) (n – 1)
let factorial acc n=如果在OCaml和其他函数语言中,一些“好的”递归调用被编译成仅仅是跳转,那么它与循环一样有效。更严格地说,“好”是指尾部位置,但在我看来,文档有意跳过这一点,因为它只是介绍性的目的。适当使用“[sic]”,但“OCaml”也不是您编写它的方式。(“OCaml”在2001年左右我写博士论文的时候就已经是应该写的了,但那时还不是正式的。)一些“好的”递归调用在OCaml和其他函数语言中被编译成仅仅是跳转,因此它和循环一样有效。更严格地说,“好”是指尾部位置,但在我看来,文档有意跳过这一点,因为它只是介绍性的目的。适当使用“[sic]”,但“OCaml”也不是您编写它的方式。(“OCaml”在2001年左右我写博士学位的时候就已经是应该写的了,但那时它不是官方的)。
let factorial n =
let loop acc n' = if n' <= 1 then acc else loop (acc * n') (n' – 1) in
loop 1 n