2014-10-20 69 views
0

我想用遞歸體在swift中編寫函數文字 - 在這種情況下,它只是將所有值添加到列表中。我收到一個錯誤,「變量在它自己的初始值中使用」。有什麼想法可能是錯誤的嗎?另外我知道我在這裏做的是一個簡單的減少,它被構建到Array中,我只是將它用作我在其他地方看到的示例。快速匿名函數遞歸

let list: Slice = [1,2,3,4,5,6,7,8,9,10] 

var closure = { (memo: Int, list: Slice<Int>) -> Int in 
    if (list.count == 0) { 
     return memo 
    } else { 
     return closure(memo + list[0], list[1..<list.count]) 
    } 
} 

let value = closure(0,list) 

回答

4

試試這個:

let list: Slice = [1,2,3,4,5,6,7,8,9,10] 

var closure:((Int, Slice<Int>) -> Int)! 
closure = { (memo, list) in 
    if (list.count == 0) { 
     closure = nil // remove retain cycle 
     return memo 
    } else { 
     return closure(memo + list[0], list[1..<list.count]) 
    } 
} 

let value = closure(0, list) 

編輯:

看到這部影片:Advanced Swift at WWDC14。從大約41:00開始。它顯示了這種方法的缺點,以及更好的解決方法。

+0

謝謝,看來關鍵是,封閉變量都將被聲明,然後再進行分配。你知道這是一個錯誤還是一個功能? – Brandon 2014-10-20 18:03:44

+0

我認爲這是一項功能。編譯器只會拒絕「在它自己的初始值內使用的變量」,這就是我們如何避免它。用'!'類型聲明變量將被初始化爲'nil',這是「初始值」。然後,作爲一個正常的關閉行爲,可以從關閉內部看到修改的「關閉」值。 – rintaro 2014-10-20 18:09:31

+0

查看我的編輯答案 – rintaro 2014-10-20 18:49:54

0

我知道這是很老,但我發現另一種選擇:

let list : ArraySlice<Int> = [1,2,3,4,5,6,7,8,9,10] 

let closure = { (Void) -> ((Int, ArraySlice<Int>) -> Int) in 
    func f(memo: Int, list: ArraySlice<Int>) -> Int { 
     if (list.count == 0) { 
     return memo 
     } else { 
     return f(memo + list[list.startIndex], list: list[(list.startIndex + 1)..<list.endIndex]) 
     } 
    } 
    return f 
}() 

let value = closure(0, list)