Day 01 - Hi, Functional Programming

Alert: 以下会将 Functinoal Programming 简称 FP.

关於我

yo! What's up

这是笔者第一次参加 IT 铁人赛,希望可以顺利完赛,请大家多多指教!!!

笔者是一位自学程序的前端工程师,一年前,因缘际会下接触到了 FP,在那之後就与 FP 爱恨纠缠直至今日...

如果把 FP 视为一座山,随着入山的时间越久,会觉得离山顶的距离越远,甚至一度想要放弃,但会有种莫名的魔力,吸引你继续探索,并且这份热情会越来越强烈,笔者认为这就是 FP 的美妙之处吧!

尽管笔者才刚入山,但还是决定把这近一年的的所学记录下来,希望能给第一天入山的山友们一点帮助,以及分享这座山的美。

FP 的学习曲线

FP 的学习曲线如同下面四种阶段 (这是仅是笔者这一年的心境,非每个人都会有这些过程,仅供参考)

  • 蜜月期: 就跟每个人第一次在 terminal 用某个程序语言印出 hello world 的兴奋感一样,FP 刚开始也会给你这种感觉,各种基础概念很容易就搜寻到,并且这些概念可以快速运用在专案中,这时候成就感爆棚的自己会甚至觉得 FP 也不过如此。但份喜悦不会维持太久,会很快发现自己错了,而且大错特错。

  • 困惑期: 这时候会发现 FP 不是只有 curry, compose, point free 这些 buzz words 这麽简单,你可能会开始接触到 functor, monad 这些从 pure FP language 来的 big words, 一开始不知道怎麽去使用它,并且对它一无所知,它会颠覆你对写程序的认知,是另外一种全新的思维去写程序。

当 functor, monad 这个概念到 JavaScript 或 TypeScript 时,讨论以及写成文章的人就会相较於 compose, curry 的少很多,也因为 资源密度开始稀疏,所以会让整个学习过程充满煎熬,此时会有停滞不前的感觉是很正常的。

  • 绝望期: 尽管知道了 functor, monad 等等的概念,但却完全不知道如何运用在专案中,并且非 FP 语言实践 FP 时,不免会有绑手绑脚的感觉,所以会开始学习其他 pure FP language, 例如 haskell, PureScript, clojure 等,而这一切都是为了提升自己的知识广度,此时也会开始想要理解 FP 的个中原理,所以会开始学习 category theory 等。 一旦熟悉了这些後,才有可能离开新手村。

  • 创伤後恢复期: 这个时期应该可以称为融会贯通时期,可以将 FP 的概念落实到各种应用上面,但笔者还没达到这个境界,或许来年的铁人赛有幸学成後再来分享。

FP 的优点

  • 可读性 (Readability): FP 相较於 imperative programming 有着更佳的可读性。而可读性带来的好处,不仅仅可以减少写程序犯错机会,也可以让读程序码的人,更舒服地理解该段程序在处理什麽逻辑。

举最简单的例子,像是我们要将一组阵列内的值 乘二 後再取 偶数

imperative approach: 是用 step by step 的方式告诉电脑 要如何 达到最终目标,这样的写法也使阅读程序的人需要一段一段地去阅读。

declarative approach: 是用更抽象的语法,专注於定义所想要的最终目标,不会去管程序该如何做。

// utils 
const double = val => val * 2; // 值乘 2
const isEven = val => !(val % 2); // 是否为偶数

// data
const arr = [1, 2, 3, 4, 5];

// imperative approach
let result = [];
for(let i = 0; i < arr.length; i++) {
    const doubledVal = double(arr[i]);
    if(isEven(doubledVal)) {
        result.push(doubledVal)
    }
}
console.log(result); // [2, 4, 6, 8, 10]

// declarative approach
const resultF = arr.map(double).filter(isEven);
console.log(resultF) // [2, 4, 6, 8, 10]
  • 可预期的 (Predictability) : 当我们在写程序时,最害怕的就是发生不可预期的错误,而 FP 本身 immutable,以及 pure function 的特性,使我们减少程序内不可预期的结果,也减少了 side effect 的产生。

  • 可复用的 (Reusble) : 每个函式只处理一件事可说是 FP 的一大特色。就好比乐高积木,每一块积木虽然只有一种功能,但当积木组合起来,就可以让创造出让人大吃一惊的模型。并且这些积木可以复用,组出各式各样的模型。

关於本系列文章

Functional Programming For Everyone

虽然说这是 Functional Programming For Everyone, 但对於初学 FP 的读者们,其内容会可能会有点深度,看一次看不懂其实是很正常的,只要持之以恒就可以理解个中精随。

而在众多程序设计典范中, FP 只是其中一种,它没有任何神奇的魔法,也不会让开发者一夕之间变成 clean code 大师,甚至会让其他人觉得这是邪魔歪道,这也是笔者想推广 FP 的原因之一,它虽然不是万灵丹(当然也不是邪魔歪道),但可以训练开发者用另一种思维去写程序,让开发者能在开发时多一种强大的武器可以运用。

目前文章规划大概会:

  1. Functional Thinking 基础概念 (Day 2 ~ Day 5)
  2. Functional Thinking 进阶概念 (Day 6 - Day 8)
  3. Functional Programming fundamental (Day 9 - Day 15)
  4. ADTs (Day 17 - Day 24)
  5. 实作小专案 (Day 25 - Day 29)
  6. 总结 (Day 30)

给读者们:

适合谁:
熟悉 JavaScript, 且对 FP 产生好奇的。

不太适合谁:
不会在 terminal 用任何语言印出 hello world 的读者们。

文章目标:

  • 推广 FP 的优点: FP 不得不说,熟练後真的可以让程序读起来像是一篇优美的文章,以及达到上面所说的优点。

  • 减少学习 FP 的 Learning Curve: 就如同上述所讲的 FP 有一定的学习曲线,而此一挑战,最低目标就是减少学习者探索资源的时间!

  • 推广 FP: 取之於社群,回馈於社群。

文章内可能会使用的套件:
Ramda / fp-ts / io-ts

小结

FP 一直都是笔者自我摸索学习的概念,而比较进阶的概念甚至不敢用在公司的专案上面,只有用 side project 练习。一方面是 FP 这个 pattern 并不是每个人都耳熟能详的,怕会造成之後承接专案的开发者维运上的负担,另一方面也没有信心有熟练到可以用在专案,希望透过这三十天的分享,梳理这近一年来的所学。

如果看到有写错的地方,请不吝啬地指正。

那我们就开始这三十天的旅程吧!


<<:  [Day7] 实作 - 敌人篇

>>:  <Day1> 前言

创建App-任务中心界面

任务中心界面 今天进行任务中心的界面页,本界面设有三大重点,点数、签到、每日任务。 而签到则以本Ap...

Day 7— 自动化回信机(4) 勾选後寄出通知信

我们已经顺利的将 onEdit(e) 以及 MailApp.sendMail(message) 学完...

Ruby on Rails Model 验证及回呼

资料验证(Validation) 回呼(Callback) 资料验证(Validation) 开发网...

线性串列的链式储存 - DAY 5

前言 资料结构由逻辑和储存结构组成,了解他们不难,难的是你想解决的问题,问题牵涉到的的现实事物,可以...

Day10-使用 create-react-app 部署第一个 React static Web

承接昨天的部分 先使用 create-react-app 将原本的静态页面置换掉 $ npx cre...