泛函編程(5)-數據結構(Functional Data Structures)

     編程即是編制對數據進行運算的過程。特殊的運算必須用特定的數據結構來支持有效運算。如果沒有數據結構的支持,我們就只能爲每條數據申明一個內存地址了,然後使用這些地址來操作這些數據,也就是我們熟悉的申明變量再對變量進行讀寫這個過程了。試想想如果沒有數據結構,那我們要申明多少個變量呢。所以說,數據結構是任何編程不可缺少的元素。

    泛函編程使用泛函數據結構(Functional Data Structure)來支持泛函程序。泛函數據結構的特點是”不可變特性“(Immutability), 是泛函編程中函數組合(composition)的必需。所以,與其它編程範疇不同,泛函編程的泛函數據結構必須具體一套特定的數據運算方式。

泛函數據結構及運算方法具備以下特徵:

1、不可變特性(Immutable)

2、運算在數據結構內進行。儘量避免使用中間變量

3、運算返回新的數據結構作爲結果

我們先看看熟悉的OOP數據運算風格:

1 scala> var arr = Array(1,2,3)
2 arr: Array[Int] = Array(1, 2, 3)
1 scala> var sum = arr(0)+arr(1)+arr(2)
2 sum: Int = 6

以上運算是需要中間變量的。而且是在結構外進行的:先把數據從地址讀出再相加。

1 scala> arr(0) = sum
2 
3 scala> arr
4 res9: Array[Int] = Array(6, 2, 3)

直接賦值後arr內容變了。在這裏arr是“可變的”(Mutable)數據結構。肯定的是如果下面需要再次使用arr時,我們是無法保證它內容一致性的。

再看看泛函風格:

 

1 scala> val arr = Array(1,2,3)
2 arr: Array[Int] = Array(1, 2, 3)
3 scala> val sum = arr.sum
4 sum: Int = 6

 

泛函運算直接在數據結構內進行,不需要中間變量。

1 scala> val arr1 = arr map { x => if(x == 1) sum else x }
2 arr1: Array[Int] = Array(6, 2, 3)
3 
4 scala> arr
5 res10: Array[Int] = Array(1, 2, 3)

arr1是賦值後新的數據結構。arr沒有變化。這樣我們可以放心使用arr來進行函數組合了。

可能這裏會出現一些誤解:arr1先複製了arr內的數據後再修改內容,所以arr沒有變。這樣理解有對也有不對:從效果來說arr1是複製了arr。但從具體做法上系統只是把arr(0)下面節點的指針指向了arr1(0),並沒有進行實質的數據複製。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章