鎮(zhèn)江技師學院 李佳琳 黃向東
本文將著重探討Swift中涵蓋高級FP的使用,因此通過現實世界情況來思考這些概念,將會在教學中對學生學習Swift有所幫助。在這種情況下,假設正在構建一個游樂園的應用程序,并且該公園的乘坐數據由遠程服務器上的API提供。在Xcode中創(chuàng)建一個新的playground。
首先將以下內容添加到playground:

通過更改變量,可以創(chuàng)建可變狀態(tài)。單獨或在相對簡單的系統(tǒng)中,可變狀態(tài)不是什么大的問題。但是,當將許多對象連接在一起時,例如在大型面向對象系統(tǒng)中,可變狀態(tài)會產生許多令人頭疼的問題。例如,當兩個或多個線程訪問相同的變量同時,它們可能會修改或訪問失靈,導致意外行為的發(fā)生。這包括競爭條件、死鎖和許多其他問題。想象一下,如果你可以編寫狀態(tài)永遠不會發(fā)生變化的代碼。并發(fā)系統(tǒng)中出現的一大堆問題就會消失。可以通過創(chuàng)建不可變狀態(tài)來執(zhí)行此操作,因此不允許在程序過程中更改數據。使用不可變數據的主要好處是:使用它的代碼單元沒有副作用,這意味著代碼中的函數不會改變自身之外的元素,并且在函數調用發(fā)生時不會出現任何怪異的效果。在本文中使用的主要數據是一個不可變的Swift常量時會發(fā)生什么。
要討論的最后一個概念是遞歸,只要函數將自身稱為其函數體的一部分,就會發(fā)生遞歸。在函數式語言中,遞歸有效地替換了命令式語言中使用的循環(huán)結構。當函數的輸入導致再次調用函數時,這被認為是遞歸情況。為了避免無限的函數調用堆棧,遞歸函數需要一個基本案例來結束它們。讓我們?yōu)槟挠螛吩O施添加遞歸排序功能。
如果等待時間較短,認為一次乘坐比另一次乘坐少,如果乘坐的名稱相同,認為它們相等。現在,擴展Array到包含一個quick-Sorted方法:


該算法首先選擇一個樞軸元素。然后將收藏分為兩部分;一部分保持所有小于或等于樞軸的元素,另一部分保持剩余元素大于樞軸。然后使用遞歸對兩部分進行排序。請注意,通過使用遞歸,不需要可變狀態(tài)。使用如下代碼驗證功能:

第二行確認quickSorted沒有修改傳入的數組。要記住的一件事是,遞歸函數確實有一些額外的內存(堆棧)使用和運行時開銷,但是它們通常比它們更混亂的命令式對應物更優(yōu)雅,并且這不應該是較小數據集的問題。
通過考慮以下問題,可以將在此學到的大部分內容與FP相結合,并清楚地展示函數式編程的一些優(yōu)點。一個有小孩的家庭希望在休息之后盡可能多地游玩,所以他們需要找到哪些適合兒童的游樂設施有最短的線路。通過等待時間少于20分鐘的所有家庭游樂設施幫助他們,并按等待時間(升序)對其進行排序。

如上所寫,命令式代碼很好,但快速瀏覽并不是很清楚,直接地了解它正在做什么。必須暫停以詳細查看算法才能掌握它。如果回來做一些維護,調試或者將其交給新開發(fā)人員怎么辦?FP可以做得更好。生成的代碼是聲明性的,這意味著它是自我解釋的,并且讀起來就像它解決的問題陳述。這與命令式代碼不同,命令式代碼類似于計算機必須采取的步驟來解決問題陳述。
通過以上實例,可以更清晰地使學生懂得,Swift不是一種純函數式語言,但它結合了多種編程范例,為提供應用程序開發(fā)的靈活性。開始使用FP技術的好地方是在Model層,ViewModel層以及應用程序的業(yè)務邏輯出現的任何位置。對于用戶界面,使用FP技術的地方不太清楚。反應式編程是用于UI開發(fā)的類似FP的方法的示例。例如,RxSwift是用于iOS和macOS編程的反應庫。通過采用功能性的聲明式方法,的代碼可以更簡潔明了。同樣,當的代碼被隔離到沒有副作用的模塊化功能時,的代碼將更容易測試。最后,隨著多處理核心成為CPU和GPU的標準,最小化副作用和并發(fā)問題將變得越來越重要,FP將是實現平穩(wěn)性能的最重要方式之一!