我們來(lái)探討一下函數(shù)式編程

看了一本叫swift函數(shù)式編程的書抄淑,每一章就問(wèn)題引入討論了一下這個(gè)思想刻剥,我們來(lái)自己理解一下育灸;首先上圖腻窒,以及寫一下傳統(tǒng)做法;

首先我們按照書中的定義

typealias Position = CGPoint
typealias Distance = CGFloat

不懂typealias的請(qǐng)自行查閱磅崭;

我們總是這樣做

  1. 圖1所示儿子,我們現(xiàn)在要表示一個(gè)未知點(diǎn)point是否在圖中黑色圈圈內(nèi),很自然的砸喻,我們傳入point參數(shù)柔逼,返回一個(gè)bool值,來(lái)解決這個(gè)問(wèn)題割岛,通常我們都會(huì)這樣思考愉适;


    inRange1
    inRange1
func inRange1(target: Position, range: Distance) -> Bool {
    return sqrt(target.x * target.x + target.y * target.y) <= range
}
  1. 那么如果我們的圓心不在(0,0)點(diǎn)呢,需要做坐標(biāo)系仿射變換(線性變換加上一個(gè)平移變換)對(duì)吧癣漆,或者理解仿射有點(diǎn)吃力维咸,我們只做平移變換,就是說(shuō)現(xiàn)在我們?cè)c(diǎn)不是(0,0)了:


    inRange2
    inRange2
func inRange2(target: Position, ownPosition: Position, range: Distance) -> Bool {
    let dx = ownPosition.x - target.x
    let dy = ownPosition.y - target.y
    let targetDistance = sqrt(pow(dx, 2.0) + pow(dy, 2.0))
    
    return targetDistance <= range
}

其實(shí)就是空間中的兩個(gè)點(diǎn)得出一個(gè)相對(duì)距離惠爽,也很簡(jiǎn)單對(duì)吧癌蓖,我們繼續(xù);

  1. 現(xiàn)在我們又有新需求了婚肆,我們要挖去中間的這個(gè)圓租副,因?yàn)槲覀兊狞c(diǎn)現(xiàn)在要在這個(gè)環(huán)上運(yùn)動(dòng)了:


    inRange34
    inRange34
let minimumDistance: Distance = 2.0
func inRange3(target: Position, ownPosition: Position, range: Distance) -> Bool {
    let dx = ownPosition.x - target.x
    let dy = ownPosition.y - target.y
    let targetDistance = sqrt(pow(dx, 2.0) + pow(dy, 2.0))
    
    return targetDistance <= range && targetDistance >= minimumDistance
}

就是需要我們挖去以原點(diǎn)為中心,半徑為minimumDistance的圓旬痹,也還好附井;

  1. 我們還要考慮如果有一個(gè)圓,讓這個(gè)圓在小圓環(huán)之外两残;
    如上圖中Friendly所示永毅;
func inRange4(target: Position, ownPosition: Position, friendly:Position, range: Distance) -> Bool {
    let dx = ownPosition.x - target.x
    let dy = ownPosition.y - target.y
    let targetDistance = sqrt(dx * dx + dy * dy)
    
    let friendlyDx = friendly.x - target.x
    let friendlyDy = friendly.y - target.y
    let friendlyDistance = sqrt(pow(friendlyDx, 2.0) + pow(friendlyDy, 2.0))
    
    return targetDistance <= range
        && targetDistance >= minimumDistance
        && friendlyDistance >= minimumDistance
}

我們還可以這樣做

的確如書上所說(shuō),我做了好多重復(fù)的工作人弓,而且從代碼復(fù)制粘貼的情況來(lái)看沼死,我似乎做了不少工作;太你太臃腫了崔赌,需要重構(gòu)意蛀!
于是我們定義了這樣一個(gè)關(guān)系耸别,它是一個(gè)關(guān)系,也是一個(gè)值县钥,作者說(shuō)函數(shù)要當(dāng)作是值來(lái)看待的秀姐;

typealias Region = (Position) -> Bool

理解起來(lái)也很容易:我是一個(gè)函數(shù),我接受一個(gè)參數(shù)若贮,你可以將Position的點(diǎn)讓我來(lái)幫你驗(yàn)證省有,如果你通過(guò)我的驗(yàn)證,那你就是我要表達(dá)的Region谴麦,我會(huì)告訴你你的參數(shù)是不是我要的結(jié)果蠢沿;
很順暢對(duì)吧!接下來(lái)我們用它來(lái)寫幾個(gè)函數(shù):

  • inRange1重寫
func circle(radius: Distance) -> Region {
    return { position in
        sqrt(pow(position.x, 2.0) + pow(position.y, 2.0)) <= radius //這不加 return 竟然也可以
    }
}
  • inRange2重寫匾效,平移變換圓
func shift(offset: Position, region: @escaping Region) -> Region {
    return { position in
        return region(Position(x: position.x + offset.x, y: position.y + offset.y))
    }
}
  • 寫一個(gè)不是我范圍的Region
func invert(region: @escaping Region) -> Region {
    return { position in
        !region(position)
    }
}
  • 來(lái)一個(gè)相交的區(qū)域
func intersection(region1: Region, region2: Region) -> Region {
    return { point in
        region1(point) && region2(point)
    }
}
  • 來(lái)一個(gè)并集的區(qū)域
func union(region1: Region, region2: Region) -> Region {
    return { point in
        region1(point) || region2(point)
    }
}
  • 再來(lái)一個(gè)差集
//函數(shù)表示在region中舷蟀,而屬于minusRegion的部分
func difference(region: Region, minusRegion: Region) -> Region {
    return intersection(region1: region, region2: invert(region: minusRegion))
}

一時(shí)間發(fā)現(xiàn)把集合的性質(zhì)寫了一個(gè)遍,那如果把這個(gè)東西寫成一個(gè)泛型面哼,用的豈不是更多野宜?
先不考慮,我們來(lái)重新寫一下之前的那個(gè)inRange4吧魔策!

最終inRange版本

func inRange(ownPosition: Position, target: Position, friendly: Position, range: Distance) -> Bool {
    //表示灰色的圓環(huán)速缨,頂點(diǎn)為(0,0)的圓環(huán)
    let rangeRegion = difference(region: circle(radius: range), minusRegion: circle(radius: minimumDistance))
    //發(fā)生了平移變換后的圓環(huán)
    let targetRegion = shift(offset: ownPosition, region: rangeRegion)
    //發(fā)生了平移變換后的朋友圈
    let friendlyRegion = shift(offset: friendly, region: circle(radius: minimumDistance))
    //最終結(jié)果為在目標(biāo)圓環(huán)中,而不在朋友圈的區(qū)域
    let resultRegion = difference(region: targetRegion, minusRegion: friendlyRegion)
    
    return resultRegion(target)
}

結(jié)論

我不知道這過(guò)程中我做了什么代乃,總的來(lái)說(shuō)我貌似理解的更清晰了旬牲,改天再研究吧!你有什么想法搁吓,我們可以探討一下霸!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末堕仔,一起剝皮案震驚了整個(gè)濱河市擂橘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摩骨,老刑警劉巖通贞,帶你破解...
    沈念sama閱讀 212,222評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異恼五,居然都是意外死亡昌罩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門灾馒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茎用,“玉大人,你說(shuō)我怎么就攤上這事」旃Γ” “怎么了旭斥?”我有些...
    開封第一講書人閱讀 157,720評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)古涧。 經(jīng)常有香客問(wèn)我垂券,道長(zhǎng),這世上最難降的妖魔是什么羡滑? 我笑而不...
    開封第一講書人閱讀 56,568評(píng)論 1 284
  • 正文 為了忘掉前任圆米,我火速辦了婚禮,結(jié)果婚禮上啄栓,老公的妹妹穿的比我還像新娘。我一直安慰自己也祠,他們只是感情好昙楚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诈嘿,像睡著了一般堪旧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奖亚,一...
    開封第一講書人閱讀 49,879評(píng)論 1 290
  • 那天淳梦,我揣著相機(jī)與錄音,去河邊找鬼昔字。 笑死爆袍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的作郭。 我是一名探鬼主播陨囊,決...
    沈念sama閱讀 39,028評(píng)論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼夹攒!你這毒婦竟也來(lái)了蜘醋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,773評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咏尝,失蹤者是張志新(化名)和其女友劉穎压语,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體编检,經(jīng)...
    沈念sama閱讀 44,220評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胎食,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了允懂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斥季。...
    茶點(diǎn)故事閱讀 38,697評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酣倾,到底是詐尸還是另有隱情舵揭,我是刑警寧澤,帶...
    沈念sama閱讀 34,360評(píng)論 4 332
  • 正文 年R本政府宣布躁锡,位于F島的核電站午绳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏映之。R本人自食惡果不足惜拦焚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杠输。 院中可真熱鬧赎败,春花似錦、人聲如沸蠢甲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鹦牛。三九已至搞糕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曼追,已是汗流浹背窍仰。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留礼殊,地道東北人驹吮。 一個(gè)月前我還...
    沈念sama閱讀 46,433評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像晶伦,于是被迫代替她去往敵國(guó)和親钥屈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評(píng)論 2 350

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