你是對的,可選項可以是一種痛苦,這就是爲什麼你不應該過度使用它們。但是,它們不僅僅是你在使用框架時必須處理的事情。他們是一個難以置信的常見問題的解決方案:如何處理返回結果的調用,可能是好的,或者可能不會。
例如,取Array.first
成員。這是一個方便的實用程序,它爲您提供數組的第一個元素。爲什麼當您撥打a[0]
時能夠撥打a.first
有用?因爲在運行時該陣列可能是空的,在這種情況下a[0]
會爆炸。當然你可以預先檢查a.count
- 但是再次
a。你可能會忘記,
and
b。這會導致相當難看的代碼。
Array.first
通過返回可選項來處理此事。因此,在可以使用數組的第一個元素的值之前,您必須展開可選項。
現在,您的問題關於僅在if let
塊內存在的解包值。設想一下並行代碼,檢查數組數量。它會是一樣的,對吧?
if a.count > 0 {
// use a[0]
}
// outside the block, no guarantee
// a[0] is valid
if let firstElement = a.first {
// use firstElement
}
// outside the block, you _can't_
// use firstElement
當然,你可以做一些事情,比如在計數爲零的時候儘早返回函數。這有效,但有點容易出錯 - 如果你忘了這麼做,或者把它放在沒有發生運行的條件語句中?基本上,您可以使用array.first
來做同樣的事情:在函數的早期檢查計數,然後再執行array.first!
。但那!
就像是給你的信號 - 要小心,你正在做一些危險的事情,如果你的代碼不完全正確,你會後悔的。
選項還有助於使選擇稍微漂亮。假設你想在數組爲空時默認值。取而代之的是:
array.count > 0 ? a[0] : somedefault
,你可以這樣寫:
array.first ?? somedefault
這是在幾個方面更好。它把重要的事情放在前面:你想要的價值是表達如何開始,然後是默認值。與三元表達式不同的是,它首先用檢查表達式觸發你,然後是你實際需要的值,最後是默認值。它也更加簡單 - 避免輸入錯誤更容易,並且不可能導致運行時爆發。
再舉一個例子:find
函數。這將檢查值是否在集合中並返回其位置的索引。但是這個價值可能不會出現在收藏中。其他語言可能會通過返回結束索引(它不指向一個值,而是一個超過最後一個值)來處理這個問題。這就是所謂的「哨兵」值 - 看起來像一個常規結果的值,但實際上有着特殊的含義。像前面的例子一樣,在使用結果之前,你必須檢查結果是不是等於結束索引。但你必須知道這樣做。您必須查看find
的文檔並確認它是如何工作的。
隨着find
返回一個可選項,當你理解可選的習慣用法時,要意識到它所做的原因是因爲結果可能因爲顯而易見的原因而無效。關於上述安全性的所有相同的事情也適用 - 您不會意外忘記,並將結果用作索引,因爲您必須首先打開它。
也就是說,您可以過度使用可選項,因爲它們是必須檢查的負擔。這就是爲什麼數組下標不返回可選項 - 這會造成很多麻煩,不得不經常檢查和解包它們,尤其是當您知道您使用的索引是有效的事實時(例如,您處於一個用於循環數組的有效索引範圍的循環),人們會不斷地使用!
,並因此混亂他們的代碼而沒有任何好處。但是,然後像第一個和最後一個這樣的幫助程序方法被添加,以涵蓋人們希望快速執行操作而不必首先檢查數組大小,但希望安全地執行操作的常見情況。
(SWIFT詞典,在另一方面,預計將通過無效標定期訪問,這就是爲什麼他們[key]
方法並返回一個可選)
更妙的是,如果能夠完全避免故障的可能性。例如,當filter
不匹配任何元素時,它不返回可選的nil
。它返回一個空數組。 「很明顯,它會」,你可能會說。但是你會驚訝你經常看到有人像數組一樣提供返回值,而實際上他們只是應該返回一個空數組。所以你完全正確地說,除非有必要,否則你應該避免選擇性 - 這只是一個必要手段的問題。在上面的例子中,我會說他們是必要的,並且是更好的解決方案。
曾聽說過面向鐵路的編程嗎?這裏有一篇文章解釋了f#中的概念http://fsharpforfunandprofit.com/posts/recipe-part2/ – mustafa
偉大的問題,看看函數式編程和(可能)函數Swift – Nick
如果您要投最後一票投票結束這個問題太主觀了,你能評論一下它有什麼特別的錯誤嗎?這個問題真的是一個我怎麼做,這個答案真的可以回答。如果你真的認爲它應該被關閉,我可以做些什麼來改進它? –