文章目錄
  1. 1. 前言
  2. 2. sequence
  3. 3. functional 來了
  4. 4. 進入擴充
    1. 4.1. OO part
    2. 4.2. functional part
  5. 5. 持續擴充中
  6. 6. 結論

阿、也許接下來會開 haskell 的坑?但、想為自己對從以前到現在對 functional 的理解下一個簡單的結論,主要是描述該用什摸樣的想法來入 OO 和 functional,他們的想法差異又在哪裡這樣,然後、希望過一段時間後回來,會發現以前的自己果然太天真了~這樣。(絕對很傻很天真、所以此篇慎入)

我希望我可以盡量的不辭窮(?) 但應該還是有點難。

前言

OO 似乎都很熟悉、就不多提了,因為我 OO 真的沒有很熟~。

對於 functional programming 從網路上找、大概都可以找到幾個好像有點虛無縹緲,好像很有道理、但其實根本不知道他在說什摸的幾個特點:

  • Higher-Order Function
  • Lambdas
  • No side effects
  • Immutable data

或者還會提到什摸 First class 之類的,但整組下來其實還是不知道 functional programming 是在幹麻…。看完後、想要寫、覺得難。
但我也沒有打算做名詞解釋啦~ 雖然、不管是名詞解釋,而且接下來的心得分享都可能是在誤導大家… T UT 但、我還是想寫寫的我想法。

sequence

一般從我們遇到問題,開始想辦法,然後開始一個個解決,可以回朔一下自己過往的經驗,幾乎都是一個個步驟取得需要的東西,然後、得到最後的結果,大概是這樣。而這種方式因為深入骨髓(?)所以、大部份也都是最容易開始的一種方式。而、我們最一開始的 c/c++ 不就是這樣嗎?書上的教學大概都是這樣:

  1. 定義變數。
  2. 開始做要做的事情
  3. 得到結果。

特別、當我們以第一人稱來描述問題的時候,會發現、哇~ 這樣好像感同身受、超容易有想法的。
然後、 OO 就是個更好拿來做這樣表現的一種方式。(我是這摸認為的啦~)

比如:

1
2
3
4
5
6
7
8
class Animal {
constructor(info) { this.info = info; }
run(time) { return this.info.speed * time; }
}
const kiki = new Animal({ speed: 10 });
kiki.run(10);

^^^
產生出(有一隻)新動物 kiki , kiki 在奔跑、跑了 10 (秒/分/小時?)。好直白、但意思就是這樣~ T UT

functional 來了

而我呢!有一陣子不喜歡 OO 那樣、所以我會把它反過來。

1
2
3
4
function run (role, time) { return role.speed * time; }
const kiki = { speed: 10 };
run(kiki, 10);

^^^
對、這種方式看起來好像有點怪,一點也不順暢、什摸叫做 跑吧 kiki 10(秒/分/小時?),好吧、祈使句的話應該還說得通啦~ XDDD

但我認為、這種方式優秀的地方,並不完全在於語句的通順(也就是可讀性),對我來說、他優秀的地方在於對於規則的描述和資料的可擴充性。

進入擴充

一般來說、寫程式很容易就會有很多很像但又有微妙不同的東西慢慢的無性生殖出來。

比如一開始我們訂了 Animal class 然後、有一隻小動物叫 kiki。接著突然知道主人要使用交通工具(也許是腳踏車、摩托車、汽車、也可能是兩條腿歐)要帶 kiki 去公園散步。

OO part

除了 Animal , 也許人類我們可以繼續沿用 Animal ,然後、交通工具我們就要再另外定。也許尼會想說、他們就一樣單純的有 speed 就好啦、我又沒有說要車牌號碼什摸的。(我們都先把案情想得很單純歐、千萬別複雜化)

但是、尼可以想像 bicycle = new Animal({ speed: 20 }) 像這樣嗎~?顯然不行吧~除非這交通工具有人工智慧或者成精了、要不、要不我認為我可能無法接受。因此、在 OO part,大概還會再定義個 Vehicle ,來擔任這角色。但是、痛苦的事情接著來了。當尼有更多不相容的類型加入的時候、代表尼需要更多的 class 來處理這件事情,偏偏他們類似,更可憐的是說不定還一模一樣????

這時候有人說尼可以用個 OO 的繼承啊!尼可以想像 VehicleAnimal 誰繼承誰嗎~ T UT? 或者他們上層在開個祖先?但祖先應該叫什摸~ 囧 有機物之類的嗎?對、我很在意這種眉眉角角,我有時候很難想像出合理的繼承啦~!所以、假設尼也想不出來只好跟我一樣無性生殖下去了。

1
2
3
4
5
6
7
8
9
10
11
class Vehicle {
constructor(info) { this.info = info }
run(time) { return this.info.speed * time; }
}
const master = new Animal({ speed: 5 });
const bicycle = new Vehicle({ speed: 15 });
const car = new Vehicle({ speed: 40 });
// 也許會有更多的 class、更多的角色加入

functional part

有趣的來了,從第一次我們定義 kiki 的時候,很明顯發現他是資料。所以、即使尼有再多種角色,他們都是資料、跟 kiki 的地位是一樣的。所以、管尼是主人、還是騎車、還是開飛機,這些都跟 kiki 一樣。(萬物皆平等、歐、萬物皆資料的概念)

所以就會變成這樣….

1
2
3
const master = { speed: 5 };
const bicycle = { speed: 15 };
const car = { speed: 40 };

那需要訂 run 嗎?不需要啊、因為 run 是一樣的!那有更多的角色呢?也都跟 kiki 是一樣的。在這邊我們可以反芻一下第一階段的程式。

結論就是:當時定義的 run 是一種規則。我定義了規則(run),然後讓角色(資料)去自由地發揮。說穿了、其實就是一個 $f(x)$ 的概念啦~ 有沒有很熟悉?國中的時候就教過啦~!我認為這是很經典的代入方法。不知道 functional 是什摸、這就是 functional 啊、啊啊啊~!

持續擴充中

接下來一定會有人說『蛤~如果我就是要大家的 run 都訂的不一樣、那尼不就要訂很多的 run , run 噴得到處都是也沒有比較好吧?』『差評!』『負分!』『OO 比較好!』

好啦、其實這也有幾種解法,其中一種解法我認為跟 functional language 的其中一個特性非常有關係。(其他的應該也有關係啦、但我好像印象不太深刻了、我不敢亂說~ T ^T 印象中應該還有好幾種寫法)

這特性就是 Higher-order Function ,也就是說、function 可以當參數跟結果。這是 functional language 一個非常重要的指標,一個語言可不可以說他是 functional (先不提純不純),我認為、一定要有這個。(好像也一定要有這個啦~)

OO 我們就跳過了,functional 的尼就可以類似這樣定,然後 run 要稍微改寫一下…。(希望沒寫錯啊、寫錯就多多包涵了)

1
2
3
4
5
6
7
const master = { speed: 5, newSpeed(speed) { return 3 * speed; } }; // 3倍速
const bicycle = { speed: 15, newSpeed(speed, a, t) { return speed + a * t / 2; } }; // 初始不為 0 的等加速度
const car = { speed: 40, newSpeed(speed, a, t) { return a * t / 2; } }; // 初始 0 的等加速度
function run (role, time) {
return role.newSpeed ? role.newSpeed(role.speed, role.a, t) * t;
}

也就是說、我訂好規則,run 就是 speed * time ,那 speed 是那個角色該定義好的的事情,要怎摸定義是他的事,當然、如果型別可以統一最好、要不就是要加個判斷。上面的 speed 和 newSpeed 的呈現方式都可以再設計得更優秀、更彈性點啦~ 現在就簡單的拼湊下而已。

這種方式的優點在於、尼會知道在尼程式裡面

  • 有一個公訂的規則,他代表的意義是不會跑掉,而且可以隨著角色(參數)變化。
  • 不需要一直的 extend ,重複的定義早就有的東西。
  • 以概括的來說,是可以不知道各個角色做了些什摸事情,然後他們有一樣的規則可以達到一樣的目的。

另外可以延伸出的幾個我很喜歡的點(但這一樣也很看人喜不喜歡)

延伸上述最後一點,我認為 functional language 弱化了 sequential programming 這件事。所有的東西(包含大家所認知的的資料和 function) 都是資料。我還記得以前在寫 lisp 一件很有趣的事情。

當時的作業是:學校提供學生的成績、然後、請訂出規則(以下列出各種科系的規則),幫各個科系取得錄取名單。

當 function 的意義代表的是規則,訂出了規則後、資料倒進來,就有種 filter 的感覺,而事實上在取得的結果,也的確可能沒有按照 data 順序(阿、我記得這好像跟 lisp 有關啦~),但這就蠻有趣的體現出 filter 、過篩,這樣的感覺。而且、像這類型的話、其實規則也沒有所謂的順序性,先後根本沒關。但如果以 sequence 的想法的話,大概就是要幾個 loop 然後搭配 if-else,反覆地進行到最後。但… functional 可以不用~ T UT 多棒啊~!

結論

其實、我不太知道這樣的描述是不是有把他們差異講得很清楚,也不太確定對不對啦~!因為幾乎沒有像其他大大們講到的各種特性、注意事項,他帶來的 balabala。我認為那很抽象,要認真地用文字描述對我來說實在是有點難,說的出來的話、我應該也可以成為大大了的感覺。而且扣掉部分的特性以外,即使是 c/c++ 也可以模擬出類似 functional 的寫法和行為,相反過來也是可以(寫過來和寫過去我都有試過歐),即使真的沒有辦法非常完整的互相模擬(可能有效能上、實際運作方式不同的差異)。不過、即使這樣、我還是認為 functional 和 oo 是一種理念、想法,而不是一種油水不相容的概念。(其實、這好像又可以是一篇啦~ XDDD 他們的互相模擬,找到新題材的意思?)

寫這篇的理由除了一開始講的要入 haskell 的坑之前先給自己做個理念的複習,等之後回來看有多幼稚以外,也因為我是 functional 控,大家突然問、我又老講不出個什摸來…所以,先寫起來放的概念~。希望可以以一種輕鬆的方式、不用各種名詞解釋就可以體會出他們的差異、希望不要再虛無縹緲了。

謝謝大家!歐、也替以後來看這篇的自己先謝謝一下寫這篇的自己!(<– 突然超正經的是壞掉了嗎?)

文章目錄
  1. 1. 前言
  2. 2. sequence
  3. 3. functional 來了
  4. 4. 進入擴充
    1. 4.1. OO part
    2. 4.2. functional part
  5. 5. 持續擴充中
  6. 6. 結論