Swift - 使用Optional的flatMap來讓nil向下傳遞

背景

當我知道Optional也有flatMap方法的時候我的內(nèi)心是很驚訝的. 之前CollectionflatMap就因為兩個重載方法搞得我暈了一陣.而且因為不常用對所以對flatMap一直沒有一個概念. 最近一些對可選值的使用場景讓我調(diào)研并使用了一下, 結合唐巧的一篇博客, 算是對flatMap這個關鍵詞有了統(tǒng)一的認識.

使用場景

假設我們要設計一個函數(shù), 函數(shù)參數(shù)是一個image的data, 我們要把它先轉換為UIImage, 然后將其轉換為jpg格式,壓縮0.3倍, 然后返回壓縮后的UIImage. 常規(guī)的話我們可能會這么寫.

func getCompressImage(by data: Data?) -> UIImage? {
        guard let data = data,
          let image = UIImage(data: data),
          let jpegImageData = image.jpegData(compressionQuality: 0.3),
          let compressImage = UIImage(data: jpegImageData) else {
            return nil
        }
        return compressImage
    }

這樣其實已經(jīng)算是比較清晰了(比起if let)

如果使用flatMap會是這樣的

func getCompressImage(by data: Data?) -> UIImage? {
     return data.flatMap {
                    UIImage(data: $0)
                }.flatMap{
                    $0.jpegData(compressionQuality: 0.3)
                }.flatMap{
                    UIImage(data: $0)
                }
    }

flatMap函數(shù)的核心思想是對一個容器的元素進行再變形,變形為新的容器, 這里的容器就是指Optional, 所以我們可以看到它可以將異常情況nil進行下沉. 在一步步的操作中我們并沒有進行解包操作, 只是將有值得情況進行處理, nil的情況向下傳遞下去. 代碼其實更清晰簡潔了.
并且不是類似的情況都能用guard let解決, 如果其中一個操作比較復雜,要進行

這樣還不能足夠表現(xiàn)flatMap的好處. 先看一段傳統(tǒng)寫法的代碼

func getValue(with stringValue: String) -> String {
        guard let number = Int(stringValue), number > 100 else {
            return "default"
        }   
        let str = String(number + 100)
        if str == "1000" {
            return str
        } else {
            return "default"
        }
    }

為了舉例子寫了一段沒有具體需求的函數(shù), 目的是為了讓它無法簡化多少.
我們看到在兩種為nil的情況下我們寫了兩次return "default"
但是使用flatMap

 func getValue(with stringValue: String) -> String {
        return Int(stringValue).flatMap {
            return $0 > 100 ? nil : String($0 + 100)
        }.flatMap {
            $0 == "1000" ? "1000" : nil
        } ?? "default"
}

我們將兩種可能為nil的情況傳遞到函數(shù)調(diào)用的末尾, 統(tǒng)一來返回default, 并且變化的過程看起來更簡單清晰了
你可以試一下如何優(yōu)化第一種代碼.. 我是不知道它如何能做到一次處理返回default

總結

flatMap雖然傳的是一個函數(shù), 里面可以做額外的操作, 但是我們最好只做變形操作.不能引發(fā)副作用是函數(shù)式編程的原則..
另外Optional的這個函數(shù)雖然看起來挺酷, 但是使用不當也會增加閱讀的復雜度,一個guard let就能解決的話還用個函數(shù)那就有些炫技的嫌疑了.
對于flatMap的nil下沉我覺得是與其它解包方式最大的區(qū)別. 大家也可以多試試.

flatMapmap區(qū)別

在函數(shù)式編程里所有的集合類型都有這兩個方法,
除了集合類型, RxSwift里的Observable,和標準庫里的Optional也有這兩個方法, 它們的共性是對某一類型的元素進行了封裝.
我們先將這個封裝了之后的類型叫做容器, 被封裝的值叫做元素
在集合類型里的元素很好理解, Optional容器里的元素就是someValue, Observable容器的元素就是觀察的值

mapflatMap都是容器將元素進行變形得到一個新的容器, 不同的是
map的變形是 元素 -> 元素
flatMap的變形是元素->容器
套用到前面的幾種容器類型就發(fā)現(xiàn)確實如此.... 主要區(qū)別在于transform函數(shù)的類型.

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妒峦,一起剝皮案震驚了整個濱河市壁袄,隨后出現(xiàn)的幾起案子牌柄,更是在濱河造成了極大的恐慌,老刑警劉巖旁涤,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝇刀,死亡現(xiàn)場離奇詭異搓萧,居然都是意外死亡毛甲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門哈扮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纬纪,“玉大人蚓再,你說我怎么就攤上這事“鳎” “怎么了对途?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長髓棋。 經(jīng)常有香客問我,道長惶洲,這世上最難降的妖魔是什么按声? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮恬吕,結果婚禮上签则,老公的妹妹穿的比我還像新娘。我一直安慰自己铐料,他們只是感情好渐裂,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钠惩,像睡著了一般柒凉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篓跛,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天膝捞,我揣著相機與錄音,去河邊找鬼愧沟。 笑死蔬咬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的沐寺。 我是一名探鬼主播林艘,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼混坞!你這毒婦竟也來了狐援?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拔第,失蹤者是張志新(化名)和其女友劉穎咕村,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚊俺,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡懈涛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了泳猬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片批钠。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡宇植,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出埋心,到底是詐尸還是另有隱情指郁,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布拷呆,位于F島的核電站闲坎,受9級特大地震影響,放射性物質發(fā)生泄漏茬斧。R本人自食惡果不足惜腰懂,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望项秉。 院中可真熱鬧绣溜,春花似錦、人聲如沸娄蔼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岁诉。三九已至锚沸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涕癣,已是汗流浹背咒吐。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留属划,地道東北人恬叹。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像同眯,于是被迫代替她去往敵國和親绽昼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容