今天是鐵人賽的最後一天,就來聊聊第一天說到的 scala 可以 Functional Programming 吧.Functional Programming 其實之前就已存在了,但為什麼最近又開始紅了起來了呢?
我覺得是因為大數據、machine learning、AI 等...技術越來越受到重視,而這些需要大量運算的環境下,無法只靠單執行緒處理運算.所以才會使用多執行緒、分散式運算、平行處理等來增加處理資料的速度.但使用這些技術解決運算速度問題的同時,也衍生出其他的問題.而 Functional Programming 是很適合用來解決這些問題,所以也越來越受到重視.
接著先介紹兩個蠻重要的觀念是Concurrency(並行)以及Parallelism(平行).
多個任務在一個 CPU(core) 上面執行,在時間內交互執行,會以為是同時處理多個工作.(multitasking on a single-core machine).
多個任務在多個 CPU(cores) 上面同時執行,同時處理多個工作.(tasks run at the same time on a multicore processor).
那面對 Concurrency 以及 Parallelism 的環境時.Imperative programming(C、C++、Java、Pythin) 在處理這些問題上就會顯得非常複雜.像 java 要寫 multi-thread 的程式時就要很小心,而且要避免一些問題,例如:deadlock.有很多共用變數或方法的地方又要加上 synchronize.所以光是處理這些問題就很令人頭痛,那會變成那麼複雜有一個很大的原因就是因為 Imperative programming 用到的變數幾乎都是 mutable 的.mutable 的變數代表它的值可以被改變、而且也可以被重新定義.那在 Concurrency 或 Parallelism 執行上,你無法確定 state 的狀況是什麼.這時候 immutable 及 pure function 的好處出來了,你不用擔心變數或function 在哪邊被重新定義了,因為 immutable 不可以被改變.所以 scala 的 collection 有 mutable 及 immutable.
開發程式時,幾乎都使用 pure functions,程式裡只使用 immutable values (scala 的 val).
Imperative 的寫法(use var & for) :
def sum(nums: List[Int]): Int = {
var sum = 0
for (i <- nums) {
sum += i }
sum
}
val lst = List(1,2,3)
sum(lst) // Int = 6
Functional 的寫法(use match & recursion) :
def sums(xs: List[Int]): Int = xs match {
case Nil => 0
case x :: tail => x + sums(tail)
}
sums(lst) // Int = 6
Imperative 的寫法(use mutable collection & for) :
def double(ints: List[Int]): List[Int] = {
val buffer = new scala.collection.mutable.ListBuffer[Int]()
for (i <- ints) {
buffer += i * 2
}
buffer.toList
}
val oldNumbers = List(1,2,3)
val newNumbers = double(oldNumbers) // List(2, 4, 6)
Functional 的寫法(use Higher Order Function(map)) :
val oldNumbers = List(1,2,3)
val newNumbers = oldNumbers.map(_ * 2) // List(2, 4, 6)