Swift:什么時候不適合使用函數式方法
發布于2015年7月24日
原文鏈接
昨天,我在代碼庫中發現了我所認為的極具Swift風格的代碼。
var minionImages = [UIImage]()
for i in 1...7 {
if let minionImage = UIImage(named: "minionIcon-\(i)") {
minionImages.append(minionImage)
}
}
這讓我立刻想到這是使用函數式解決方案來進行重構的絕佳機會。哦吼吼!我可以做函數式編程了!!!是的,我非常激動。
那么,明顯的解決方案是在這兒使用map:
let minionImagesMapped = (1...7)
.map { UIImage(named: "minionIcon-\($0)") }
我對自己感到很滿意。這段代碼只有一行AND函數。但這樣做無法滿足之前的一個必要條件-這個數組得是UIImages [UIImage]
數組,但是這段代碼返回的是可選類型 UIImages [UIImage?]
數組。
所以我google了下,然后為了得到非可選類型UIImages數組的可接受的函數式解決方案是這樣的:
let minionImagesFiltered = (1...7)
.map { UIImage(named: "minionIcon-\($0)") }
.filter { $0 != nil}
.map { $0! }
這樣的確有用,但是我并不開森。這段代碼又長又拙笨,而且我討厭不得不強迫解包可選類型,盡管這樣做是安全的。然而,主要的原因還是這樣看起來并不像原生for循環那樣簡單有效。從以下代碼可以看的很清楚:

可能我這樣做是錯的,但是我最后選擇了for循環。從中得到的教訓:有時候在Swift中使用for循環是正確的解決方案。當然我可能在這里遺漏了一些東西,很高興能在評論中聽到你們的想法!
升級##
由于有些童鞋在下面的評論中以及Twitter上指出,可以在這里使用Swift2.0的flatMap
作為函數式解決方案:
let minionImagesFlattened = (1...7).flatMap { UIImage(named: "minionIcon-\($0)") }
在這里,我不得不誠實的說,每次我看到有關flatMap
的內容時,我并不能完全理解它做了什么或是怎么做的。它并不像map
以及filter
那樣給我的感覺自然。我不懂它在這兒是怎么做的,所以我不得不多查一下。
這讓我再次得出結論,我無法確認這對于代碼可讀性是最好的方式。如果那些對Swift和函數式編程了解很少的人看我的代碼的話,他們能理解發生了神馬嗎?同時,我可以確定的是,每個人只需看一眼就能夠理解for循環。