![對(duì)函數(shù)式語(yǔ)言的誤解_第1頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-11/14/e337ad5b-ee50-4187-ab50-6ca575eedd24/e337ad5b-ee50-4187-ab50-6ca575eedd241.gif)
![對(duì)函數(shù)式語(yǔ)言的誤解_第2頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-11/14/e337ad5b-ee50-4187-ab50-6ca575eedd24/e337ad5b-ee50-4187-ab50-6ca575eedd242.gif)
![對(duì)函數(shù)式語(yǔ)言的誤解_第3頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-11/14/e337ad5b-ee50-4187-ab50-6ca575eedd24/e337ad5b-ee50-4187-ab50-6ca575eedd243.gif)
![對(duì)函數(shù)式語(yǔ)言的誤解_第4頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-11/14/e337ad5b-ee50-4187-ab50-6ca575eedd24/e337ad5b-ee50-4187-ab50-6ca575eedd244.gif)
![對(duì)函數(shù)式語(yǔ)言的誤解_第5頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-11/14/e337ad5b-ee50-4187-ab50-6ca575eedd24/e337ad5b-ee50-4187-ab50-6ca575eedd245.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、對(duì)函數(shù)式語(yǔ)言的誤解很早的時(shí)候,“函數(shù)式語(yǔ)言”對(duì)于我來(lái)說(shuō)就是 Lisp,因?yàn)?Lisp 可以在程序的幾乎任何位置定義函數(shù),并且把它們作為值來(lái)傳遞(這叫做 first-class function)。后來(lái)有人告訴我,Lisp 其實(shí)不算是“函數(shù)式語(yǔ)言”,因?yàn)?Lisp 的函數(shù)并不“純”(pure)。所謂“純函數(shù)”的意思,就是像數(shù)學(xué)的函數(shù)一樣,如果你給它同樣的輸入,它就給你同樣的輸出。然后你就發(fā)現(xiàn)在這種定義下,幾乎所有程序語(yǔ)言里面常見(jiàn)的隨機(jī)數(shù)函數(shù)(random),其實(shí)都不是“純函數(shù)”。因?yàn)槊恳淮握{(diào)用 random(),你都會(huì)得到不同的隨機(jī)數(shù)。在這種害怕自己所用的語(yǔ)言“不純”的恐慌之下,我開(kāi)始
2、接觸 Haskell,一種號(hào)稱(chēng)“純函數(shù)式”的語(yǔ)言。Haskell 的社區(qū)喜歡在他們的概念里省掉“純”這個(gè)字,把 Haskell 叫做“函數(shù)式語(yǔ)言”。他們喜歡“糾正”別人的概念。他們告訴人們,“不純”的函數(shù)式語(yǔ)言,其實(shí)都不配叫做“函數(shù)式語(yǔ)言”。在他們的這種定義下,Lisp 這么老牌的函數(shù)式語(yǔ)言,居然都不能叫“函數(shù)式語(yǔ)言”了。但是看完這篇文章你就會(huì)發(fā)現(xiàn),其實(shí)他們的這種定義是狹隘和錯(cuò)誤的。在 Haskell 里面,你不能使用通常語(yǔ)言里面都有的賦值語(yǔ)句,比如 Pascal 里的 x:=1,C 和 Java 里的 x=1,或者 Scheme 里的(set! x 1),Common L
3、isp 里的 (setq x 1)。這樣一來(lái),你就不可能保留“狀態(tài)”(state)。所謂“狀態(tài)”,就是指“隨機(jī)數(shù)種子”那樣的東西,其實(shí)本質(zhì)上就是“全局變量”。比如,在 C 語(yǔ)言里定義 random() 函數(shù),你可以這么做:int random() static int seed = 0; seed = next_random(seed); return seed; 這里的 seed 是一個(gè)“static 變量”,其本質(zhì)就是一個(gè)全局變量,只不過(guò)這個(gè)全局變量只能被 random 這一個(gè)函數(shù)訪問(wèn)。每次調(diào)用 random(
4、),它都會(huì)使用 next_random(seed) 生成下一個(gè)隨機(jī)數(shù),并且把 seed 的值更新為這個(gè)新的隨機(jī)數(shù)。在random() 的執(zhí)行結(jié)束之后,seed 會(huì)一直保存這個(gè)值。下一次調(diào)用 random(),它就會(huì)根據(jù) seed 保存的值,算出下一個(gè)隨機(jī)數(shù),然后再次更新 seed,如此繼續(xù)。這就是為什么每一次調(diào)用 random(),你都會(huì)得到不同的隨機(jī)數(shù)。可是在 Haskell 里面情況就很不一樣了。由于 Haskell 不能保留狀態(tài),所以同一個(gè)“變量”在它作用域的任何位置都具有相同的
5、值。每一個(gè)函數(shù)只要輸入相同,就會(huì)輸出同樣的結(jié)果。所以在 Haskell 里面,你不能輕松的表達(dá) random 這樣的“不純函數(shù)”。為了讓 random 在每次調(diào)用得到不同的輸出,你必須給它“不同的輸入”。那怎么才能給它不同的輸入呢?Haskell 采用的辦法,就是把“種子”作為輸入,然后返回兩個(gè)值:新的隨機(jī)數(shù)和新的種子,然后想辦法把這個(gè)新的種子傳遞給下一次的 random 調(diào)用。所以 Haskell 的 random 的“線路”看起來(lái)像這個(gè)樣子:(舊種子)-> (新隨機(jī)數(shù),新種子)現(xiàn)在問(wèn)題來(lái)了。得到的這個(gè)新種
6、子,必須被準(zhǔn)確無(wú)誤的傳遞到下一個(gè)使用 random 的地方,否則你就沒(méi)法生成下一個(gè)隨機(jī)數(shù)。因?yàn)闆](méi)有地方可以讓你“暫存”這個(gè)種子,所以為了把種子傳遞到下一個(gè)使用它的地方,你經(jīng)常需要讓種子“穿過(guò)”一系列的函數(shù),才能到達(dá)目的地。種子經(jīng)過(guò)的“路徑”上的所有函數(shù),必須增加一個(gè)參數(shù)(舊種子),并且增加一個(gè)返回值(新種子)。這就像是用一根吸管扎穿這個(gè)函數(shù),兩頭通風(fēng),這樣種子就可以不受干擾的通過(guò)。所以你看到了,為了達(dá)到“純函數(shù)”的目標(biāo),我們需要做很多“管道工”的工作,這增加了程序的復(fù)雜性和工作量。如果我們可以把種子存放在一個(gè)全局變量里,到需要的時(shí)候才去取,那就根本不需要把它傳來(lái)傳去的。除&
7、#160;random() 之外的代碼,都不需要知道種子的存在。為了減輕視覺(jué)負(fù)擔(dān)和維護(hù)這些進(jìn)進(jìn)出出的“狀態(tài)”,Haskell 引入了一種叫 monad 的概念。它的本質(zhì)是使用類(lèi)型系統(tǒng)的“重載”(overloading),把這些多出來(lái)的參數(shù)和返回值,掩蓋在類(lèi)型里面。這就像把亂七八糟的電線塞進(jìn)了接線盒似的,雖然表面上看起來(lái)清爽了一些,底下的復(fù)雜性卻是不可能消除的。有時(shí)候我很納悶,在其它語(yǔ)言里易如反掌的事情,為什么到 Haskell 里面就變成了“研究性問(wèn)題”,很多時(shí)候就是 monad 這東西在搗鬼。特別是當(dāng)你有多個(gè)“狀態(tài)”的時(shí)候,你就需要使用像 monad transformer 這樣的
8、東西。而 monad transformer 在本質(zhì)上其實(shí)是一個(gè)丑陋的 hack,它并不能從根本上解決問(wèn)題,卻可以讓你傷透腦筋也寫(xiě)不出來(lái)。有些人以為會(huì)用 monad 和 monad transformer 就說(shuō)明他水平高,其實(shí)這根本就是自己跟自己過(guò)不去而已。當(dāng)談到 monad 的時(shí)候,我喜歡打這樣一個(gè)比方:使用含有 monad 的“純函數(shù)式語(yǔ)言”,就像生活在一個(gè)沒(méi)有電磁波的世界。在這個(gè)世界里面沒(méi)有收音機(jī),沒(méi)有手機(jī),沒(méi)有衛(wèi)星電視,沒(méi)有無(wú)線網(wǎng),甚至沒(méi)有光!這個(gè)世界里的所有東西都是“有線”的。你需要絞盡腦汁,把這些電線準(zhǔn)確無(wú)誤的通過(guò)特殊的“接線器”(monad)連接起來(lái),才能讓你的各種信息處理設(shè)備能
9、夠正常工作,才能讓你自己能夠看見(jiàn)東西。如果你想生活在這樣的世界里的話,那就請(qǐng)繼續(xù)使用 Haskell。其實(shí)要達(dá)到純函數(shù)式語(yǔ)言的這種“純”的效果,你根本不需要使用像 Haskell 這樣完全排斥“賦值語(yǔ)句”的語(yǔ)言。你甚至不需要使用 Lisp 這樣的“非純”函數(shù)式語(yǔ)言。你完全可以用 C 語(yǔ)言,甚至匯編語(yǔ)言,達(dá)到同樣的效果。我只舉一個(gè)非常簡(jiǎn)單的例子,在 C 語(yǔ)言里面定義如下的函數(shù)。雖然函數(shù)體里面含有賦值語(yǔ)句,它卻是一個(gè)真正意義上的“純函數(shù)”:int f(int x) int y = 0; int z = 0; y = 2 * x; z = y + 1; return z / 3; 這是為什么呢?因?yàn)?/p>
10、它計(jì)算的是數(shù)學(xué)函數(shù) f(x) = (2x+1)/3 。你給它同樣的輸入,肯定會(huì)得到同樣的輸出。函數(shù)里雖然對(duì) y 和 z 進(jìn)行了賦值,但這種賦值都是“局部”的,它們不會(huì)留下“狀態(tài)”。所以這個(gè)函數(shù)雖然使用了被“純函數(shù)程序員”們唾棄的賦值語(yǔ)句,卻仍然完全的符合“純函數(shù)”的定義。如果你研究過(guò)編譯器,就會(huì)理解其中的道理。因?yàn)檫@個(gè)函數(shù)里的 y 和 z,不過(guò)是函數(shù)的“數(shù)據(jù)流”里的一些“中間節(jié)點(diǎn)”,它們的用途是用來(lái)暫存一些“中間結(jié)果”。這些局部的賦值操作,跟函數(shù)調(diào)用時(shí)的“參數(shù)傳遞”沒(méi)有本質(zhì)的區(qū)別,它們不過(guò)都是把信息傳送到
11、指定的節(jié)點(diǎn)而已。如果你不相信的話,我現(xiàn)在就可以把這些賦值語(yǔ)句全都改寫(xiě)成函數(shù)調(diào)用:int f(int x) return g(2 * x);int g(int y) return h(y + 1);int h(int z) return z/3; 很顯然,這兩個(gè) f 的定義是完全等價(jià)的,然而第二個(gè)定義卻沒(méi)有任何賦值語(yǔ)句。第一個(gè)函數(shù)里對(duì) y 和 z 的“賦值語(yǔ)句”,被轉(zhuǎn)換成了等價(jià)的“參數(shù)傳遞”。這兩個(gè)程序如果經(jīng)過(guò)我寫(xiě)的編譯器,會(huì)生成一模一樣的機(jī)器代碼。所以如果你說(shuō)賦值語(yǔ)句是錯(cuò)誤的話,那么函數(shù)調(diào)用也應(yīng)該是錯(cuò)誤的了。那我們還要不要寫(xiě)程序了?盲目的排斥賦值語(yǔ)句,來(lái)
12、自于對(duì)“純函數(shù)”這個(gè)概念的片面理解。很多研究像 Haskell,ML 一類(lèi)語(yǔ)言的專(zhuān)家,其實(shí)并不明白我上面講的道理。他們仿佛覺(jué)得如果使用了賦值,函數(shù)就肯定不“純”了似的。CMU 的教授 Robert Harper 就是這樣一個(gè)極端。他在一篇博文里指出,人們不應(yīng)該把程序里的“變量”叫做“變量”,因?yàn)樗鷶?shù)學(xué)和邏輯學(xué)里所謂的“變量”不是一回事,它可以被賦值。然而,其果真如他所說(shuō)的那樣嗎?如果你理解了我對(duì)上面的例子的分析,你就會(huì)發(fā)現(xiàn)其實(shí)程序里的“變量”,跟數(shù)學(xué)和邏輯學(xué)里面的“變量”相比,其實(shí)并沒(méi)有本質(zhì)的不同。程序里的變量甚至更加嚴(yán)格一些。如果你把數(shù)學(xué)看作一種程序語(yǔ)言的話,恐怕沒(méi)有一本數(shù)學(xué)書(shū)可以編譯通過(guò)
13、。因?yàn)樗鼈兝锩娉錆M了變量名沖突,未定義變量,類(lèi)型錯(cuò)誤等程序設(shè)計(jì)的低級(jí)錯(cuò)誤。你只需要注意概率論里表示隨機(jī)數(shù)的大寫(xiě)變量(比如 X),就會(huì)發(fā)現(xiàn)數(shù)學(xué)所謂的“變量”其實(shí)是多么的不嚴(yán)謹(jǐn)。這變量 X 根本不需要被賦值,它自己身上就帶“副作用”!實(shí)際上,90%以上的數(shù)學(xué)家都寫(xiě)不出像樣的程序來(lái)。所以拿數(shù)學(xué)的“變量”來(lái)衡量程序語(yǔ)言的“變量”,其實(shí)是顛倒了。我們應(yīng)該用程序的“變量”來(lái)衡量數(shù)學(xué)的“變量”,這樣數(shù)學(xué)的語(yǔ)言才會(huì)有所改善。邏輯學(xué)家雖然有他們的價(jià)值,但他們并不是先知,并不總是對(duì)的。由于沉迷于對(duì)符號(hào)的熱愛(ài),他們經(jīng)??床坏绞挛锏谋举|(zhì)。雖然他們理解很多符號(hào)公式和推理規(guī)則,但他們卻經(jīng)常不明白這些符號(hào)和推理規(guī)則,到底代
14、表著自然界中的什么物體,所以有時(shí)候他們連最基本的問(wèn)題都會(huì)搞錯(cuò)(比如他們有時(shí)候會(huì)混淆“全稱(chēng)量詞”的作用域)。邏輯學(xué)家們的教條主義和崇古作風(fēng),也許就是圖靈當(dāng)年在 Church 手下做學(xué)生那么孤立,那么痛苦的原因。也就是這個(gè)圖靈,在某種程度上超越了 Church,把一部分人從邏輯學(xué)的死板思維模式下解放了出來(lái),變成了“計(jì)算機(jī)科學(xué)家”。當(dāng)然其中某些計(jì)算機(jī)科學(xué)家墮入了另外一種極端,他們對(duì)邏輯學(xué)已有的精華一無(wú)所知,所以搞出一些完全沒(méi)有原則的設(shè)計(jì),然而這不是這篇文章的主題。所以綜上所述,我們完全沒(méi)有必要追求什么“純函數(shù)式語(yǔ)言”,因?yàn)槲覀兛梢栽诓灰鸹煜那疤嵯率褂觅x值語(yǔ)句,而寫(xiě)出真正的“純函數(shù)”來(lái)??梢宰杂傻膶?duì)變量進(jìn)行賦值的語(yǔ)言,其實(shí)超越了通常的數(shù)理邏輯的表達(dá)能力。如果你不相信這一點(diǎn),就請(qǐng)想一想,數(shù)理邏輯的公式有沒(méi)有能力推斷出明天的天氣?為什
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2.1+2.3 地圖的閱讀 (解析版)
- 2025年民辦合肥財(cái)經(jīng)職業(yè)學(xué)院高職單招高職單招英語(yǔ)2016-2024歷年頻考點(diǎn)試題含答案解析
- 上海市普陀區(qū)初一月考試卷
- 10kV配電站房工程設(shè)計(jì)方案與實(shí)施細(xì)節(jié)
- 幼兒園主題班會(huì)活動(dòng)策劃方案五篇
- 幼兒園中班科學(xué)活動(dòng)策劃方案五篇
- 幼兒園園務(wù)調(diào)整活動(dòng)方案模板五篇
- 標(biāo)準(zhǔn)租房合同協(xié)議
- 汽車(chē)居間協(xié)議合同
- 勞務(wù)合同協(xié)議書(shū)
- 《白蛇緣起》賞析
- Interstellar-星際穿越課件
- 蘇教版2022-2023學(xué)年三年級(jí)數(shù)學(xué)下冊(cè)開(kāi)學(xué)摸底考試卷(五)含答案與解析
- 2023學(xué)年度第一學(xué)期高三英語(yǔ)備課組工作總結(jié)
- 臨建標(biāo)準(zhǔn)化圖集新版
- 安監(jiān)人員考核細(xì)則(2篇)
- 生活老師培訓(xùn)資料課件
- 腹主動(dòng)脈瘤(護(hù)理業(yè)務(wù)學(xué)習(xí))
- 注射用醋酸亮丙瑞林微球
- 大學(xué)生就業(yè)指導(dǎo)PPT(第2版)全套完整教學(xué)課件
- 家具安裝工培訓(xùn)教案優(yōu)質(zhì)資料
評(píng)論
0/150
提交評(píng)論