2011-05-09 145 views
3

我目前正在玩斯卡拉斯無阻塞期貨又名。承諾。我努力使下面的函數尾遞歸:尾遞歸和斯卡拉承諾

@tailrec 
private def repeat(res: Promise[I]):Promise[I] = 
    res map p flatMap { 
    (b:Boolean) => 
     if(b) repeat(res flatMap f) else res 
    } 

其中pI=>Boolean型和f謂詞是 型I=>Promise[I]併發功能。

該方法在沒有註釋的情況下編譯。

任何提示?謝謝

回答

4

你的方法根本不是遞歸的。 res是一個可能在另一個線程中運行的計算。就您的方法而言,res map p flatMap f將立即返回承諾。重現到repeat將發生在另一個過程中。

稍微簡潔些,Promise是繼續monad,flatMap調用會自動轉換爲繼續傳遞樣式。

1

雖然這看起來是尾遞歸的,因爲調用在代碼中只出現一次,但您有多個遞歸調用 - 您的集合中的每個元素都有一個調用。至少這就是編譯器所看到的。 (假設這是某個集合上的flatMap;我不知道p會返回什麼)

您將遞歸作爲匿名函數傳遞給某個地方。沒有人知道它將被執行多久。

+0

感謝您的回答。但是你有沒有想過我可以如何解決這個問題而不被阻塞? – paradigmatic 2011-05-09 15:09:18

+2

對不起,但我不熟悉scalaz。我試圖找出代碼中的'p'調用是失敗的。你能想到你的代碼使用while循環的程序版本嗎?如果這是不可能的,那就不可能有tco。 – ziggystar 2011-05-09 15:49:49

+1

「,您的集合中的每個元素都有一個,至少這是編譯器看到的。」是不正確的,恕我直言:'Promise'不是一個集合,編譯器只看到一個調用(不在尾部位置)。然而,第二段既正確又足以解釋爲什麼這不是尾遞歸。 – 2011-05-09 19:04:40