你问我们如何正式检查这个,所以我会刺伤。我们首先必须定义函数是尾递归的意思。形式
let rec f x_1 ... x_n = e
的递归函数的定义是尾递归如果f
内e
所有呼叫都尾调用 - 即。发生在尾部情况下。甲尾上下文C
感应定义为术语具有孔[]
:
C ::= []
| e
| let p = e in C
| e; C
| match e with p_1 -> C | ... | p_n -> C
| if e then C else C
其中e
是F#表达,x
是可变的,并且是p
的图案。我们应该把它扩展到相互递归的函数定义,但我会把它作为一个练习。
现在让我们将这个应用到您的示例中。在函数体内rec_algo1
唯一的呼叫在这方面:
if step = dSs then J
else
let a = Array.init (Array2D.length1 M) (fun i -> minby1J i M J)
let argmin = a|> Array.minBy snd |> fst
[]
而且因为这是一个尾背景下,功能是尾递归。这就是函数程序员如何看待它 - 扫描递归调用定义的主体,然后验证每个调用是否发生在尾部上下文中。一个更直观的尾部呼叫定义是除了返回呼叫之外没有其他任何操作的结果。
你可以有条不紊地检查编译器是否认识到它(毕竟,这是最重要的),但不是不向编译器询问相应分析过程的结果(或者实施一些你自己并希望它们不是更聪明比编译器)。 – delnan 2011-04-27 19:49:04
这可能会也可能不会回答你的第二个问题,但是,如果你的函数在递归调用后没有做任何事情,那么它是尾递归的。一个迹象表明它不是尾递归的:你正在做递归调用的返回值,除了返回它。 – Daniel 2011-04-27 21:04:28
参见http://stackoverflow.com/questions/806712/how-do-i-know-if-a-function-is-tail-recursive-in-f – Brian 2011-04-27 22:16:33