push-3
其中foo不是尾递归
let rec f1 = fun x -> if x = 0 then 1 else f1 (f1 0) in ...
let rec f2 = fun x -> if x = 0 then foo x else f2 x in ...
其中foo是尾递归
答案 0 :(得分:1)
你不应该问这个函数是否是尾递归的。您应该询问所有呼叫是否是尾部呼叫。另外,foo
是否是尾递归实际上是不相关的 - 尾调用是尾调用,而不管它调用哪个函数。
所以,让我们一次拿一个:
let rec f1 = fun x -> if x = 0 then 1 else f1 (f1 0) in ...
在else
中,对f1
的内部调用不是尾调用。外面的是。请注意,这意味着,根据您定义术语的方式,您可以说这个函数是尾递归(它有自己的尾调用)或者它不是&#39 ; t(它对自己进行了非尾调用)。
这就是为什么关注哪些调用是尾调用而不是尾递归这一点非常重要!具有尾部调用消除功能的语言将为外部调用而不是内部调用执行此操作。
let rec f2 = fun x -> if x = 0 then foo x else f2 x in ...
let rec f3 = fun x -> if x = 0 then foo x else f3 x in ...
在这两种情况下,对foo
和f2
的调用均为尾调用。同样,foo
是什么并不重要。
答案 1 :(得分:0)
所有这些都是尾递归。
然而, f1
包含两个递归调用,其中只有外部是尾调用。
对于f2
/ f3
,foo
是否是尾递归并不重要,因为它不是f2
/ {{递归的一部分1}}。