swift之函式式程式設計

2022-09-17 10:39:09 字數 4661 閱讀 3640

最近初學swift,和oc比,發現語言更現代,也有了更多的特性。如何寫好swift**,也許,熟練使用新特性寫出更優秀的**,就是答案。今天先從大的方向談談swift中的程式設計正規化-函式式程式設計。主要還是讀了大佬帖子,寫寫自己的理解。

"函式式程式設計"是一種"程式設計正規化"(programming paradigm),也就是如何編寫程式的方**。

它屬於"結構化程式設計"的一種,主要思想是把運算過程盡量寫成一系列巢狀的函式呼叫。

它使**更像自然語言,告訴程式設計師要幹什麼,而不是怎麼幹,把怎麼幹的細節拆分到各個函式中。呼叫的地方邏輯清晰,便於debug。

舉例來說,現在有這樣乙個數學表示式:

(1 + 2) * 3 - 4

傳統的過程式程式設計,可能這樣寫:

var a = 1 + 2

;var b = a * 3

;var c = b - 4;

函式式程式設計要求使用函式,我們可以把運算過程定義為不同的函式,然後寫成下面這樣:

var result = subtract(multiply(add(1,2), 3), 4);

這就是函式式程式設計。

**簡潔,開發快速

函式式程式設計大量使用函式,減少了**的重複,因此程式比較短,開發速度較快。

接近自然語言,易於理解

函式式程式設計的自由度很高,可以寫出很接近自然語言的**。我們把程式的邏輯分成了幾個函式,這樣一來,我們的**邏輯也會變得幾個小碎片,於是我們讀**時要考慮的上下文就少了很多,閱讀**也會更容易。 而把**邏輯封裝成了函式後,我們就相當於給每個相對獨立的程式邏輯取了個名字,於是**成了自解釋的。

前文曾經將表示式(1 + 2) * 3 - 4,寫成函式式語言:

subtract(multiply(add(1,2), 3), 4)

對它進行變形,不難得到另一種寫法:

add(1,2).multiply(3).subtract(4)

更方便的**管理

函式式程式設計不依賴、也不會改變外界的狀態,只要給定輸入引數,返回的結果必定相同。因此,每乙個函式都可以被看做獨立單元,很有利於進行單元測試(unit testing)和除錯(debugging),以及模組化組合。

易於"併發程式設計"

函式式程式設計不需要考慮"死鎖"(deadlock),因為它不修改變數,所以根本不存在"鎖"執行緒的問題。不必擔心乙個執行緒的資料,被另乙個執行緒修改,所以可以很放心地把工作分攤到多個執行緒,部署"併發程式設計"(concurrency)。

所謂"第一等公民"(first class),指的是函式與其他資料型別一樣,處於平等地位,可以賦值給其他變數,也可以作為引數,傳入另乙個函式,或者作為別的函式的返回值。

舉例來說,下面**中的print變數就是乙個函式,可以作為另乙個函式的引數。

var print =function(i);

[1,2,3].foreach(print);

函式(function)這個名詞來自於數學,函式通過乙個給定的值,計算出另外乙個值,也就是上學時常見的f(x)。

在通常的理解中,下面**裡面,f1,f2,f3通常都被叫做函式:

//

偽** 函式無入參,返回2

def f1(): return2//

函式有引數x,返回 x+1

def f2(int x): return x+1

//函式無入參,無返回值,列印hello world

def f3(): print("

hello world

")

複製**但實際上,函式(function)和procedure是有區別的: function 通過運算返回乙個值,而procedure只執行一段**,沒有返回值。 這一點對於後面的理解是非常有幫助的,首先要區分出二者。

再回到上面的**中,f1,f2,為function而f3為procedure。

pure:純的; 單純的; 純真的; 乾淨的 我們將滿足下面兩個條件的函式稱作pure function:

side effect

函式呼叫後不會對外部狀態產生影響,比如下面這段**中sum函式是no side effect的:

def sum(a,b): return a+b

產生side effect的函式長成什麼樣呢?其實經常會寫這樣的函式:

int sum = 0

def plus(a,b)

plus函式除了計算引數之和以外,還改變了外部變數sum的值,我們plus這個函式產生了side effect。 常見的side effect

引用透明(referential transparency),指的是函式的執行不依賴於外部變數或"狀態",只依賴於輸入的引數,任何時候只要引數相同,引用函式所得到的返回值總是相同的。

有了前面的第三點和第四點,這點是很顯然的。其他型別的語言,函式的返回值往往與系統狀態有關,不同的狀態之下,返回值是不一樣的。這就叫"引用不透明",很不利於觀察和理解程式的行為。

先說兩個概念型的名詞:

高階函式(high order func),指可以將其他函式作為引數或者返回結果的函式。

一級函式(first class func),指可以出現在任何其他構件(比如變數)地方的函式。

map 

map

一般用在集合型別,對集合裡的元素進行遍歷,函式體裡實現對每乙個元素的操作。

var arr = [1,3,2,4

]let mapres =arr.map

// 執行結果:["no.1", "no.3", "no.2", "no.4"]

reduce

reduce(result)

一般用在集合型別,對集合裡的元素進行疊加處理,函式體裡傳兩個引數,第乙個是之前的疊加結果,第二個是當前元素,返回值是對當前元素疊加後的結果。

//

對陣列裡的元素:奇數相加,偶數相乘

var arr = [1,3,2,4

]let reduceres = arr.reduce((0,1))

else}//

執行結果:(4,8)

filter

filter

一般用在集合型別,對集合裡的元素進行篩選。函式體裡實現篩選條件,返回 true 的元素通過篩選。

var arr = [1,3,2,4

]let filterres =arr.filter

//執行結果:[2,4]

flatmap

首先先看下 swift 原始碼裡對集合陣列的map和flatmap的實現:

//

sequence.swift

extension sequence }//

sequencealgorithms.swift.gyb

extension sequence

public func flatmap(_ transform: (element) -> s) ->[s.element] {}

}

前面我們已經知道,map是一種遍歷,而上面的**又顯示出來,flatmap有兩種過載的函式:

其中一種與map非常相似,差別只在閉包裡的返回值變成了可選型別。 另一種稍微有點不同,閉包傳入的是陣列,最後返回的是陣列的元素組成的集合。

//

maplet arr = [1,2,nil,4,nil,5

]let arrres = arr.map //

結果為:[optional(1), optional(2), nil, optional(4), nil, optional(5)]

//flatmap

let brr = [1,2,nil,4,nil,5

]let brrres = brr.flatmap //

結果為:[1, 2, 4, 5]

let crr = [[1,2,4],[5,3,2

]]let ccres = crr.flatmap //

結果為:[1, 2, 4, 5, 3, 2]

let cdres = crr.flatmap

} //

結果為[1, 4, 16, 25, 9, 4]

//使用 map 實現的上面平鋪功能

let ceres = array(crr.map.joined()) //

同 ccres

let cfres = array(crr.map.joined()).map //

同 cdres

簡單理解為,flatmap可以將多維陣列平鋪,也還以過濾掉一維陣列中的nil元素。

map和flatmap不只在陣列中可以使用,對於 optional 型別也是可以進行操作的。先看下面這個例子:

let a: date? =date()

let formatter =dateformatter()

formatter.datestyle =.medium

let c = a.map(formatter.string

(from:))

let d = a == nil ? nil : formatter.string(from: a!)

c 和 d 是兩種不同的寫法,c 寫法是不是更優雅一些?

Python之 函式式程式設計

f lambda x x 2 定義函式f x x 2 g lambda x,y x y 定義函式g x,y x y 假設有乙個列表a 1,2,3 要給列表中的每個元素都加2得到乙個新列表,利用列表解析,我們可以這樣寫 b i 2 for i in a 利用map函式我們可以這樣寫 b map lam...

JS 之 函式式程式設計

由若干個純函式 偏函式 柯里化函式組合成乙個新的函式,同時,形成資料傳遞。挑選了一系列所需要的函式,把他們組合在一起,可以實現公共合作的效果。示例 function combination x var arr combination add,spl,toupper 三個函式,三個函式的資料都是相關聯...

Python之函式式程式設計

1 map map 函式接收兩個引數,乙個是函式,乙個是iterable,map將傳入的函式依次作用到序列的每個元素,並把結果作為新的iterator返回。def f x return x x r map f,1,2,3,4,5,6,7,8,9 print list r 1,4,9,16,25,36...