欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

從歷史講起JavaScript基因里的函數(shù)式編程實(shí)例

 更新時(shí)間:2022年10月15日 09:19:59   作者:掘金安東尼  
這篇文章主要為大家介紹了從歷史講起JavaScript基因里的函數(shù)式編程實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本篇序言

本瓜很喜歡看歷史,讀史可知興替、使人明智,作為程序員看“技術(shù)的演替歷史”同樣如此。過(guò)程是越看越有味,仿佛先賢智慧的光照亮了我原本封閉的心,每每只能感嘆一個(gè)“服”字。所以,專欄第一篇打算先從技術(shù)歷史講起,從函數(shù)式編程的淵源講起。

看完本篇:

你會(huì)知道為什么有人會(huì)說(shuō) “計(jì)算機(jī)是數(shù)學(xué)家一次失敗思考的產(chǎn)物”

你會(huì)知道為什么 “ lambda 演算定義函數(shù)有效計(jì)算” ;

你會(huì)知道編程概念中 “閉包最初是如何形成的”

你還會(huì)知道為什么標(biāo)題要說(shuō) “JavaScript 基因里寫著函數(shù)式編程” ;

話不多說(shuō),開沖了~ ??‍??‍??‍

一、數(shù)學(xué)之美

函數(shù)式編程的歷史最早可以追溯到 1930 年,一個(gè)叫 丘奇(Church)的人,提出了 λ (lambda)演算,這是所有函數(shù)式編程語(yǔ)言的基礎(chǔ)。

那這人為啥要提出這個(gè)演算?1930 年這個(gè)時(shí)間比世界上第一臺(tái)計(jì)算機(jī)誕生的時(shí)間都還要早 16 年。提出這個(gè)肯定不是因?yàn)橛?jì)算機(jī)編程。

沒錯(cuò),他是為了解決一個(gè)數(shù)學(xué)問(wèn)題。

這個(gè)數(shù)學(xué)問(wèn)題是:

著名的希爾伯特第十問(wèn)題—— 判定問(wèn)題 (1900 年提出)

我們不妨來(lái)“淺看”一下這個(gè)數(shù)學(xué)問(wèn)題,可以說(shuō)這個(gè)問(wèn)題促使了計(jì)算機(jī)的形成。

什么是希爾伯特第十問(wèn)題之判定問(wèn)題?

本瓜嘗試用通俗的表達(dá)解釋一下:

很簡(jiǎn)單,有下列這樣一個(gè)方程:

其中所有的數(shù)(aj、bj、c)都是整數(shù),求:能否找到一組 xj (全部為整數(shù))的解?

乍一看這個(gè)公式有點(diǎn)費(fèi)解。。。

其實(shí)我們可以構(gòu)建一個(gè)大家都熟悉的實(shí)例,保證一看就明白了~

我敲,這不就是勾股定理嗎?勾三股四弦五,老祖宗在西周時(shí)就發(fā)現(xiàn)了。

符合判定問(wèn)題的實(shí)例方程還有很多,比如:裴蜀等式、佩爾方程、四平方和定理、以及著名的【費(fèi)馬大猜想】等等。

噢!希爾伯特提出判定問(wèn)題,旨在“一勞永逸”,如果這個(gè)問(wèn)題被解決了,那么它的子問(wèn)題也都能被同樣解決。所以,在 1900 年到 1930 年之間,以希爾伯特為代表的數(shù)學(xué)家們 試圖構(gòu)建一個(gè)自動(dòng)化定理證明的系統(tǒng),讓公理系統(tǒng)內(nèi)的所有命題都能用一套既定的規(guī)則得以證明或證偽。

說(shuō)白了,就是這群數(shù)學(xué)家也想偷懶,證明各類數(shù)學(xué)公式已經(jīng)累了,想搞點(diǎn)自動(dòng)化的通用流程,能夠用通用流程去證明或證偽數(shù)學(xué)難題。

大家都在前赴后繼的嘗試解決這個(gè)問(wèn)題,直到 1930 年后,出現(xiàn)了 哥德爾、圖靈、丘奇 這些人,他們幾乎在同一時(shí)間,但又在不同角度對(duì)這個(gè)問(wèn)題作出了解釋。

更為神奇的是,最終證明他們的結(jié)論竟然是等效的。

哥德爾不完備性定理中遞歸函數(shù) == 圖靈完備 == lambda 演算

他們徹底解決了希爾伯特第十問(wèn)題嗎?

很遺憾,并沒有。

不過(guò)在這個(gè)過(guò)程中,他們搞清楚了一個(gè)很重要的問(wèn)題,一個(gè)對(duì)計(jì)算機(jī)科學(xué)至關(guān)重要的元核心問(wèn)題:

什么樣的函數(shù)是可以有效計(jì)算的?!

在這之前,數(shù)學(xué)家們對(duì)于這個(gè)問(wèn)題并沒有一個(gè)普遍結(jié)論,只知道一些最簡(jiǎn)單的函數(shù),以及通過(guò)簡(jiǎn)單規(guī)則將簡(jiǎn)單函數(shù)組合起來(lái)的函數(shù)(比如加法),是可以有效計(jì)算的。

這種感覺像是無(wú)心插柳,本來(lái)大家是沖著解決數(shù)學(xué)公式論證問(wèn)題去的,最后不約而同的得出了“函數(shù)可有效計(jì)算”的定義。這個(gè)定義由此發(fā)展,成為了 21 世紀(jì)最具顛覆力量的學(xué)科 —— 計(jì)算機(jī)。

所以才有人說(shuō):計(jì)算機(jī)是數(shù)學(xué)家一次失敗思考的產(chǎn)物。

數(shù)學(xué)的局限也會(huì)造成計(jì)算機(jī)的局限。

不過(guò)依然無(wú)法掩蓋數(shù)學(xué)之美,美在它足夠基礎(chǔ),但又隱藏著巨大的能量,影響著萬(wàn)事萬(wàn)物。

二、lambda 演算核心

各位,你有想過(guò),什么樣的函數(shù)是可以有效計(jì)算的?

如果由你定義,你會(huì)從怎樣的角度去思考?

  • 由于本篇重點(diǎn)是講函數(shù)式編程起源的 lambda 演算,所以哥德爾和圖靈的解釋不作展開,在文尾有相關(guān)文章推薦,可自行了解。(尤其是圖靈機(jī),一定多看看、體會(huì)體會(huì))

丘奇給出了它的觀點(diǎn):

有效計(jì)算的函數(shù)指的是:函數(shù)每一步都可被事先確定,而且該函數(shù)可在有限的步數(shù)之內(nèi)生成結(jié)果。

通俗來(lái)理解,“有效”即要在有限步驟內(nèi)產(chǎn)生確定的結(jié)果。

天才的丘奇給出了 lambda 演算表達(dá)式:

lambda x . body

其中 x 是輸入的參數(shù),body 是運(yùn)算過(guò)程,意思是 x 經(jīng)過(guò) body 的運(yùn)算,然后返回結(jié)果。

lambda 演算的偉大之處在于它非常簡(jiǎn)潔,揭示了計(jì)算的本質(zhì)。

細(xì)看 lambda 表達(dá)式,你會(huì)發(fā)現(xiàn)函數(shù)只能接受一個(gè)參數(shù),如果我們需要傳兩個(gè)參數(shù)呢?

其實(shí)也是能實(shí)現(xiàn)的,如下:

lambda x. ( lambda y. plus x y )

這就是沿用至今的函數(shù)式編程 柯里化 思想,傳入?yún)?shù) x,經(jīng)過(guò)運(yùn)算體 body:lambda y. plus x y 的運(yùn)算,body 又是一個(gè) lambda 運(yùn)算表達(dá)式,入?yún)⑹?y,新的運(yùn)算體是 plus x y。

這種簡(jiǎn)化的設(shè)計(jì),讓我們無(wú)需過(guò)多的語(yǔ)法,便能實(shí)現(xiàn)接收多個(gè)參數(shù)。

lambda 演算核心還有兩條重要的規(guī)則:轉(zhuǎn)換 和 規(guī)約

  • 轉(zhuǎn)換

轉(zhuǎn)換的意思是:變量的名稱并不重要,比如以下兩種寫法是等效的,相當(dāng)于變量名只是形參而已。

lambda x. ( lambda y. plus x y )
lambda y. ( lambda x. plus x y )
  • 規(guī)約

規(guī)約的意思是:我們可以對(duì)這個(gè)函數(shù)體中和對(duì)應(yīng)函數(shù)標(biāo)識(shí)符相關(guān)的部分做替換,替換方法是把標(biāo)識(shí)符用參數(shù)值替換。

舉個(gè)例子:

(lambda x . x + 1) 3
// 規(guī)約后
3 + 1

這樣寫意味著 3 是形參 x 實(shí)際的值,數(shù)值“3”可直接取代引用的參數(shù)“x”,規(guī)約后即為 3 + 1

(lambda y . (lambda x . x + y)) q
// 規(guī)約后
lambda x . x + q

首先 q 是形參 y 實(shí)際的值,規(guī)約后,實(shí)際上就是求 lambda x . x + q

規(guī)約遠(yuǎn)能做的很多變化,正是由于規(guī)約的存在,讓 lambda 演算可以實(shí)現(xiàn)遞歸,才讓它可以等效于圖靈完備。

我們?cè)賮?lái)概括一下:

  • lambda 核心表達(dá)式:lambda x . body,簡(jiǎn)潔而優(yōu)雅;
  • 入?yún)⒅挥幸粋€(gè),可以通過(guò)柯里化來(lái)實(shí)現(xiàn)接受多個(gè)參數(shù);
  • lambda 演算的“規(guī)約”規(guī)則是它實(shí)現(xiàn)復(fù)雜運(yùn)算的重要機(jī)制,由繁化簡(jiǎn);
  • 多問(wèn)一句:把函數(shù)作為 body 返回,不正是 JavaScript 高階函數(shù)的意思嗎?

可見,現(xiàn)在很多我們覺得稀松平常的一些用法,其實(shí)早在近 100 年前就被提出來(lái)了,不可謂不震撼。

三、JavaScript 的基因

說(shuō)了半天,終于來(lái)到了我們的 JavaScript,相信大家接觸 JavaScript 之初都會(huì)被“閉包”這個(gè)概念搞得有點(diǎn)蒙,為什么要這樣設(shè)計(jì)?我平常又確實(shí)用不上,好不容易學(xué)了個(gè)防抖、節(jié)流函數(shù),你就不要再繼續(xù)追問(wèn)“什么是閉包了”。

兄弟,有福了,這次帶你見識(shí)最初的閉包是如何產(chǎn)生的!

閉包的概念,在計(jì)算機(jī)誕生之前就被設(shè)計(jì)出來(lái)了,沒錯(cuò),還是來(lái)源于我們的 lambda 演算。

lambda 演算規(guī)定:

如果一個(gè)標(biāo)識(shí)符是一個(gè)閉合 lambda 表達(dá)式的參數(shù),我們則稱這個(gè)標(biāo)識(shí)符是被綁定的;如果一個(gè)標(biāo)識(shí)符在任何封閉的上下文中都沒有綁定,那么它被稱為自由變量。

比如:

lambda x . plus x y

在這個(gè)表達(dá)式中,x是被綁定的,因?yàn)樗呛瘮?shù)定義的閉合表達(dá)式 plus x y 的參數(shù)。而 y 是自由變量;

再比如:

lambda y . (lambda x . plus x y)

在內(nèi)層演算 lambda x . plus x y 中,x 是被綁定的,y 是自由的;而在完整表達(dá)中,x 和 y 是都是被綁定的:x 受內(nèi)層綁定,而 y 由剩下的外層演算綁定。

這正是 JavaScript 閉包最初的雛形, 內(nèi)部函數(shù)保持著對(duì)函數(shù)外部變量的引用。這里“被綁定的”意思就是變量不能被清理的,是以后會(huì)被用到的。

神奇嗎?閉包早于計(jì)算機(jī)誕生,仿佛就像打火機(jī)早于火柴發(fā)明一樣,讓人有點(diǎn)意外~

好了,最后說(shuō)一說(shuō):為什么 JavaScript 基因里寫著函數(shù)式編程 ?

這一段歷史,應(yīng)該很多工友早爛熟于心,網(wǎng)景公司想給 HTML 加一個(gè)腳本語(yǔ)言用于改善交互,于是招來(lái)了 布蘭登·艾克,這老哥 10 天就把這門語(yǔ)言的框架設(shè)計(jì)好了。它思想上基于 Self 語(yǔ)言和 Scheme 語(yǔ)言,語(yǔ)法上和 C 語(yǔ)言相似。

我們?cè)倏催@里的 Scheme 語(yǔ)言,它其實(shí)就是一門堂堂正正的函數(shù)式編程語(yǔ)言,它是第一大函數(shù)式編程語(yǔ)言 Lisp (1958 年)兩種方言的其中一種。而 Lisp 則來(lái)源于 lambda 演算,來(lái)源于 丘奇,來(lái)源于那個(gè)解決 1900 年數(shù)學(xué)問(wèn)題的意外收獲!

時(shí)間線是這樣的:

  • => 1900 年希爾伯特?cái)?shù)學(xué)問(wèn)題
  • => 1930 年丘奇 lambda 演算
  • => 1958 年 Lisp 語(yǔ)言
  • => 1975 年 Scheme 語(yǔ)言
  • => 1995 年 JavaScript 語(yǔ)言

知道從哪里來(lái),才能知道往哪里去。

所以,朋友們,我們現(xiàn)在所用的 JavaScript,基因里有一個(gè)重要的組成部分是函數(shù)式,把函數(shù)放在第一位、關(guān)注輸入輸出、參數(shù)柯里化、高級(jí)函數(shù)等等,在近百年里逐漸演進(jìn)。前段時(shí)間,看到一篇文章,JSON 之父吐槽說(shuō):現(xiàn)在我們更關(guān)注于把 JavaScript 的使用規(guī)模擴(kuò)大,而不是關(guān)注怎樣使這門語(yǔ)言變得更好。然后導(dǎo)致他建議退役 JavaScript,我大受震撼?;蛟S,如果某一天,ES 版本迭代關(guān)注點(diǎn)只有:又新增了幾個(gè)語(yǔ)法糖,而忽略了這門語(yǔ)言最初的設(shè)計(jì)思想,忽略去完善它,那真有點(diǎn)可惜。

以上就是從歷史講起JavaScript基因里的函數(shù)式編程實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于JavaScript基因函數(shù)式編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論