你問我們如何正式檢查這個,所以我會刺傷。我們首先必須定義函數是尾遞歸的意思。形式
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