欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
跨越邊界: 用 Haskell 研究函數性編程
                                                   

                                               

 

結構化編程和面向對象編程都革新了業(yè)務(wù)應用程序構建的方式。但是還存在其他編程模型,有些夢(mèng)想家還認為這些范式比面向對象編程的生產(chǎn)力更高。這篇文章探索 Haskell 研究函數性編程的基礎。學(xué)習函數性編程可以重塑對于 Java? 編程的思考方式。

過(guò)去 50 年中,企業(yè)所使用的語(yǔ)言 —— COBOL、C、C++ 和 Java 語(yǔ)言,都是命令式 語(yǔ)言;它們讓您告訴您的程序如何 去完成其任務(wù)。函數性 編程語(yǔ)言讓您告訴程序去做什么。這篇文章通過(guò)介紹 Haskell 來(lái)研究函數性編程。(如果您閱讀過(guò)我的跨越邊界 系列中 關(guān)于使用另外一種函數性語(yǔ)言 Erlang 進(jìn)行并發(fā)性編程的文章,可能已經(jīng)有了一定的基礎。)

在我研究超越 Java(請參閱 參考資料)時(shí),我采訪(fǎng)的三位專(zhuān)家提到了 Haskell,他們認為我應該探索一下這種語(yǔ)言。當時(shí),我并不認為市場(chǎng)已經(jīng)為函數性編程做好了準備,因為這一范式對于大多數程序員來(lái)說(shuō)都太陌生了。我現在仍然不認為我們已經(jīng)做好了準備。但是我開(kāi)始欣賞函數性語(yǔ)言帶來(lái)的生產(chǎn)力和強大力量。我只是剛剛接觸 Haskell,但這種語(yǔ)言已經(jīng)影響了我使用 Java 和 Ruby 語(yǔ)言解決問(wèn)題的方式。

命令式語(yǔ)言及其不足

關(guān)于本系列

跨越邊界 系列中,作者 Bruce Tate 推動(dòng)了這樣一個(gè)概念:今天的 Java 程序員可以通過(guò)學(xué)習其他方式和語(yǔ)言受益。Java 技術(shù)曾經(jīng)是編程陣營(yíng)中所有開(kāi)發(fā)項目的最佳選擇,但這種情況已經(jīng)發(fā)生了變化。其他框架正在塑造 Java 框架的構建方式,從其他語(yǔ)言中學(xué)到的概念有助于 Java 編程。所編寫(xiě)的 Python(或 Ruby、Smalltalk 或 ... 請自由填空)代碼可以改變您編寫(xiě) Java 代碼的方式。

本系列介紹了完全不同于 Java 開(kāi)發(fā),但又直接適用于 Java 開(kāi)發(fā)的編程概念和技術(shù)。在某些情況下,需要集成之后才能利用這些技術(shù)。在其他情況下,則可以直接應用這些概念。單獨的工具不如其他語(yǔ)言和框架影響 Java 社區的開(kāi)發(fā)人員、框架、甚至基本手段的這個(gè)概念重要。

命令式編程由一系列帶有明確順序的語(yǔ)句構成,它們的算法和編程構造嚴重依賴(lài)于應用程序的狀態(tài)。很難想像沒(méi)有這些特征的編程語(yǔ)言,因為命令式語(yǔ)言 “告訴我如何做” 的方式是如此深刻地確立在我們的日常編程哲學(xué)中。命令式編程明確塑造了您的思維方式。但通過(guò)學(xué)習替代的函數性編程工具,可以擴展您思考問(wèn)題的方式。請考慮以下這些命令式結構:

  • 賦值。命令式編程的用戶(hù)對賦值的依賴(lài)要超過(guò)其他編程技術(shù)。函數性編程最多允許為每個(gè)變量賦值一次。改變值的賦值被叫做 破壞性賦值,是不允許的。例如,多數函數性語(yǔ)言不允許 x = x + 1。

  • 迭代。命令式編程利用迭代來(lái)處理許多不同類(lèi)型的數據結構。許多命令式控制依賴(lài)破壞性賦值進(jìn)行迭代。

  • 副作用。在命令式語(yǔ)言中,輸入相同而可能返回不同值的方法,都有副作用。而對應用程序的狀態(tài)變量有影響的方法也有副作用。函數性編程沒(méi)有副作用。

如果以前沒(méi)用過(guò)函數性語(yǔ)言,那么就很難想像如何編寫(xiě)沒(méi)有破壞性賦值和副作用的應用程序。但是這些基本特征給命令性語(yǔ)言帶來(lái)了一些更嚴重的問(wèn)題:

  • 正確性問(wèn)題。有副作用的方法可能返回一個(gè)值,但同時(shí)也修改了應用程序的狀態(tài)。副作用把驗證程序正確的數學(xué)問(wèn)題復雜化。但是復雜不僅僅是數學(xué)問(wèn)題:副作用還使得測試、理解、分析和記錄程序的行為更加困難。

  • 基于順序的 bug。許多優(yōu)化依賴(lài)于對關(guān)鍵編程指令重新排序來(lái)提高性能。當依賴(lài)特定順序的程序被重新排序時(shí),錯誤就發(fā)生了。

  • 并發(fā)性問(wèn)題??勺儬顟B(tài)消失時(shí),差不多所有的并發(fā)性問(wèn)題也隨之消失。Brian Goetz 在 Java Concurrency in Practice(請參閱 參考資料)中,用 “這是愚蠢的可變狀態(tài)“ 規則結束了第一章。

不管信還是不信,不必強行規定操作的順序或承擔副作用,也可以有效地編程。





回頁(yè)首


函數性編程簡(jiǎn)介

在數學(xué)中,函數把每個(gè)輸入映射到一個(gè)特定的輸出。函數性編程范式使用數學(xué)函數表達程序。函數性語(yǔ)言并不執行命令,而是通過(guò)表示、計算數學(xué)函數來(lái)解決問(wèn)題。函數性語(yǔ)言通常有以下兩個(gè)特征:

  • 不可變的數據。純粹的函數性語(yǔ)言不依賴(lài)保存或檢索狀態(tài)的操作,因此不允許破壞性賦值。
  • 無(wú)副作用。用相同的輸入調用函數,總是返回相同的值。

對大多數函數性語(yǔ)言來(lái)說(shuō),這有點(diǎn)過(guò)于簡(jiǎn)化,但是只是過(guò)了一點(diǎn)點(diǎn)。函數叫做單體(monad),被用來(lái)以數學(xué)方式表達狀態(tài)的變化,而 Haskell 這樣的函數性語(yǔ)言則用單體來(lái)處理輸入/輸出并管理狀態(tài)中的變化。

看到函數性編程的一些局限性后,您可能認為這種編程范式是一種倒退,但請繼續往下閱讀。函數性語(yǔ)言不是軟弱無(wú)力的。實(shí)際上,語(yǔ)言專(zhuān)家們通常相信函數性語(yǔ)言操作的抽象級別要比面向對象語(yǔ)言高。它們提供了命令式語(yǔ)言通常不提供的一些工具。在這篇文章中,將看到一些工具的工作效果。





回頁(yè)首


使用 Haskell

有兩個(gè) Haskell 實(shí)現值得注意:Hugs 和 Glasgow Haskell Compiler(GHC)(請參閱 參考資料)。還有許多其他 Haskell 編譯器和解釋器,包括 Hugs 和 GHC 的分支,但是它們是主要的兩個(gè)。如果剛接觸 Haskell,那么 Hugs 解釋器是個(gè)不錯的選擇,因為它安裝和理解起來(lái)都比較容易。Hugs 有兩方面嚴重的限制:它缺乏編譯器,不能使用獨立函數;必須從文件裝入全部函數。更嚴謹的程序員會(huì )采用 GHC。它的解釋器略慢一些,但是它有編譯器模式,還允許獨立函數。在這篇文章中,我使用 Hugs,所以如果您想根據本文編寫(xiě)代碼,也應當使用它,因為這兩套軟件使用的術(shù)語(yǔ)略有不同。

用 Hugs 編碼

請下載適合您操作系統的 Hugs (請參閱 參考資料)并啟動(dòng)它。我把我信任的 Macbook Pro 放在一邊,而用我的 Windows 機器,這是為了得到一個(gè)可以快速安裝的環(huán)境。WinHugs 這個(gè) Hugs 實(shí)現在 Windows 平臺上有一個(gè)簡(jiǎn)單的一按即可的安裝程序。

將看到一個(gè)帶有 Hugs 提示符的解釋器窗口。啟動(dòng)即可。輸入一些數字和數學(xué)表達式,如清單 1 所示。將看到 Hugs 返回數學(xué)表達式的結果。這正是在函數性語(yǔ)言中期待的行為。


清單 1. 在 Hugs 解釋器中計算
Haskell 98 mode: Restart with command line option -98 to enable extensions                        Type :? for help                        Hugs>5                        5                        Hugs>5+4                        9                        

Haskell 擁有強大的類(lèi)型模型。語(yǔ)言是強類(lèi)型的,這意味著(zhù)您只能在類(lèi)型的某個(gè)實(shí)例上完成允許的操作。(例如,如果想把數字添加到字符串上,Hugs 會(huì )報錯。)Haskell 是靜態(tài)類(lèi)型化的,所以一旦給變量分配了值,那么變量就會(huì )一直維持相同的類(lèi)型。Haskell 會(huì )做一些類(lèi)型推斷,這意味著(zhù)它會(huì )根據程序中的語(yǔ)義線(xiàn)索來(lái)推斷元素的類(lèi)型,所以您會(huì )看到我在使用 有些函數時(shí)沒(méi)有聲明相關(guān)的類(lèi)型。如果使用類(lèi)型模糊不清或者在函數中使用不支持的類(lèi)型,Haskell 會(huì )報錯。Haskell 還有子類(lèi)型,而且完全是多態(tài)的;這些特性超出了本文的范圍,但如果您對此感興趣,它們也值得研究。

既然已經(jīng)看到了一些原語(yǔ)類(lèi)型,例如整型,現在可以繼續了解一些更為復雜的類(lèi)型了。通常,一個(gè)語(yǔ)言中可用的數據結構定義了語(yǔ)言的使用方式。C 使用 struct、Java 使用 class。Haskell 不使用這兩種數據結構。

Haskell 中最突出的三種數據結構是:tuple、列表(list)用戶(hù)定義的類(lèi)型。我將著(zhù)重介紹前兩種。tuple 要包含于括號 ( ) 之中,它有固定長(cháng)度。tuple 包含固定類(lèi)型的原語(yǔ)元素,甚至可以包含其他 tuple 或列表。相比之下,列表的長(cháng)度可變,由同類(lèi)元素構成。用 [ ] 包含列表。您可使用 Hugs 來(lái)體會(huì ) tuple 和列表,如清單 2 所示:


清單 2. 表示簡(jiǎn)單的 tuple 和列表
Hugs> [1,2]                        [1,2]                        Hugs> [1,"a"]                        ERROR - Cannot infer instance                        *** Instance   : Num [Char]                        *** Expression : [1,"a"]                        Hugs> (1,2,3)                        (1,2,3)                        Hugs> (1,"a")                        (1,"a")                        Hugs> [(1,2),(3,4)]                        [(1,2),(3,4)]                        Hugs> [(1,2),(3,4),(5,6,7)]                        ERROR - Type error in list                        *** Expression     : [(1,2),(3,4),(5,6,7)]                        *** Term           : (5,6,7)                        *** Type           : (c,d,e)                        *** Does not match : (a,b)                        

在清單 2 中,可以看到 tuple 中的每個(gè)元素可以是不同類(lèi)型的,但列表中的元素必須是相同類(lèi)型的。而且,如果您使用一個(gè) tuple 列表,那么每個(gè) tuple 的長(cháng)度必須相同,每個(gè) tuple 中的第 n 個(gè)元素必須與列表中所有其他 tuple 中的第 n 個(gè)元素匹配。

如您所料,Haskell 有許多在列表上操作的函數。最簡(jiǎn)單的就是 headtail。 head 返回列表的第一個(gè)元素,tail 返回其他的元素。清單 3 顯示了一些簡(jiǎn)單的列表函數:


清單 3. 簡(jiǎn)單的 Haskell 列表函數
Hugs> [1,2,3,4,5]                        [1,2,3,4,5]                        Hugs> length [1,2,3,4,5]                        5                        Hugs> head [1,2,3,4,5]                        1                        Hugs> tail [1,2,3,4,5]                        [2,3,4,5]                        

在清單 3 中,可以看到 head 返回了一個(gè)元素,tail 返回了一列元素。稍后還會(huì )看到(在 編寫(xiě)函數 中)這些函數如何構成了 Haskell 中眾多遞歸函數的基礎。

在構建列表時(shí),使用 : 操作符,叫做構造(cons) 操作符(用來(lái)構造)。構建列表時(shí),只是把元素傳遞給另一個(gè)列表??梢园言S多構建操作串在一起。

字符串只是字符列表的語(yǔ)法代稱(chēng)而已,像 [1,2,3] 這樣的列表則是 1:2:3:[] 的語(yǔ)法代稱(chēng)。這個(gè)特性使得字符串操作更容易實(shí)現。清單 4 顯示了構造操作符的的工作方式以及如何用一個(gè)字符序列構建一個(gè)字符串:


清單 4. 用構造操作符構建列表
Hugs> 6:[]                        [6]                        Hugs> 6:[7]                        [6,7]                        Hugs> 6:7:[]                        [6,7]                        Hugs> ‘d‘:‘o‘:‘g‘:‘ ‘:‘h‘:‘a(chǎn)‘:‘s‘:‘ ‘:‘f‘:‘l‘:‘e‘:‘a(chǎn)‘:‘s‘:[]                        "dog has fleas"                        

在 Haskell 中,您會(huì )發(fā)現在字符串和列表中這種語(yǔ)法代稱(chēng)非常普遍。 但是只要記?。阂磺卸际呛瘮?。

把函數當成數據

Haskell 允許把函數當成數據。這項重要的功能讓眾多的 Haskell 函數可以接受函數作為參數。這個(gè)策略讓您能夠用不同的方式把函數應用到函數的每個(gè)元素。清單 5 顯示了一系列函數,它們把函數應用到列表的每個(gè)元素:


清單 5. 把函數作為參數傳遞
Hugs> :l Char                        Char> map toUpper "Hello"                        "HELLO"                        Char> filter isUpper "To Be or Not to Be"                        "TBNB"                        Char> foldr (max) 0 [1,2,3,2,1]                        3                        Char> foldr (+) 0 [1,2,3,2,1]                        9                        

:l 命令裝入模塊。然后可以調用 Char 模塊中的函數。(其他版本的 Haskell 支持 Char.toUpper,但是 Hugs 不支持,所以要先裝入模塊,然后再利用模塊中的函數。)第一個(gè)語(yǔ)句在列表的每個(gè)元素上調用函數(本例中為 toUpper,用于把字符轉成大寫(xiě))。因為 Haskell 的字符串就是字符列表,所以得到的是 "HELLO" 字符串。filter 函數為列表的每個(gè)元素調用一個(gè)測試函數,測試函數返回布爾值,當測試函數返回 True 時(shí),還包含列表的元素。

fold 函數要略微復雜一些。它有兩種形式:foldlfoldr。fold 函數接受一個(gè)函數、一個(gè)元素和一個(gè)列表??梢赃@樣來(lái)看待 fold 函數:

  1. 從列表的左側(foldl)右側(foldr)開(kāi)始放置元素。
  2. 把操作符放在列表的所有元素之間。
  3. 從列表的一側到另一側應用操作符,對于 foldl 是從左側開(kāi)始,對于 foldr 是從右側開(kāi)始。

例如,foldr (+) 0 [1,2,3] 可歸納為 1 + (2 + (3 + 0)) 也就是 6。有些時(shí)候,順序會(huì )有影響,這就是為什么 Haskell 既提供了 foldr(右聯(lián),從右至左構建)又提供了 foldl (左聯(lián),從左至右構建)的原因。在處理列表時(shí),fold 函數提供了累積任何二進(jìn)制計算結果的好方法。

把函數組合起來(lái)

在 Haskell 程序中,可以用許多不同的方式組合函數。用復雜的方式組合函數,是函數性語(yǔ)言生產(chǎn)力的關(guān)鍵,這是因為這可不斷提高抽象的層次。

用復雜的方式組合函數,是函數性語(yǔ)言生產(chǎn)力的關(guān)鍵,這是因為這可不斷提高抽象的層次。

例如,假設有一個(gè) Java 應用程序,它計算句子中大寫(xiě)字母的數量。需要對列表進(jìn)行迭代,每遇到一個(gè)大寫(xiě)字母,就要將一個(gè)本地變量加 1。在 Haskell 中,只需用 length (filter (isUpper) "To Be or Not to Be") 取得過(guò)濾列表的長(cháng)度即可。Haskell 程序員就是這樣避免了使用破壞性更新。每個(gè)函數都在內部保存中間結果,程序員不必考慮這類(lèi)細節。





回頁(yè)首


編寫(xiě)函數

如果您使用的是 Hugs,那么需要在獨立的源文件中編寫(xiě)函數。WinHugs 可以很好的集成我的編輯器,所以不會(huì )造成太大的負擔。應當把函數放在模塊中,然后用 :l 命令裝入模塊。在清單 5 中已經(jīng)看到,我裝入了系統模塊 Char。模塊名稱(chēng)以及包含模塊的文件,要用大寫(xiě)字母開(kāi)始.函數名用小寫(xiě)字母開(kāi)始。Haskell 程序文件的擴展名是 .hs。

可以注意到:Haskell 程序頻繁地用遞歸來(lái)解決問(wèn)題。Java 開(kāi)發(fā)人員由于性能的原因和堆棧深度的限制,通常會(huì )避免遞歸。在處理遞歸時(shí),Haskell 有兩大優(yōu)勢:Haskell 優(yōu)化了尾部遞歸,Haskell 是惰性的。

尾部遞歸優(yōu)化意味著(zhù)當遞歸發(fā)生在函數末尾時(shí),編譯器或解釋器可以把遞歸表示成迭代。尾部遞歸優(yōu)化沒(méi)有堆棧開(kāi)銷(xiāo),所以這個(gè)策略降低了把遞歸處理成簡(jiǎn)單迭代的成本。為了理解 “惰性” 的含義,請把以下函數輸入名為 Generate.hs 的文件:

generate = 1:generate                        

這個(gè)函數是 1 的無(wú)窮列表。更精確地說(shuō),generate 通過(guò)構造操作符,把 1 添加到 generate —— 最初是個(gè)空列表。如果裝入并執行這個(gè)函數,就會(huì )進(jìn)入無(wú)窮遞歸循環(huán),因為沒(méi)有什么能夠停止遞歸。但奇怪的是,可以在應用程序中使用 generate 的結果,如清單 6 所示:


清單 6. Generate.hs 中的惰性遞歸
Hugs> :l Generate                        Main> head generate                        1                        Main> head (tail generate)                        1                        

雖然 generate 代表 1 的無(wú)窮列表,但 Haskell 只計算列表中自己需要的部分。在清單 6 中,第一個(gè)命令裝入函數,第二個(gè)得到頭(或第一個(gè))元素,第三個(gè)命令得到末尾的頭(或第二個(gè))元素。Haskell 只計算列表的頭兩個(gè)元素。剩下的被延遲,只在需要的時(shí)候計算。這種惰性處理的風(fēng)格使得函數性語(yǔ)言的效率出人意料,而且支持其他編程語(yǔ)言中得不到的叫做無(wú)限流 的強大抽象(請參閱 參考資料)。

在大多數教程中可以發(fā)現的大多數經(jīng)典 Haskell 函數都是遞歸的數學(xué)函數,例如 Fibonacci 函數和階乘。Fibonacci 序列的定義是:由 1 和 1 開(kāi)始的序列前兩個(gè)數字的和。所以,Fibonacci 序列的前五個(gè)數字是 1、1、(1+1) = 2、(1+2) = 3 和 (2+3) = 5。Haskell 實(shí)現的這個(gè)序列與它的數學(xué)定義非常相似,如清單 7 所示:


清單 7. fib.hs 中的 Fibonacci 序列
fib 1 = 1                        fib 2 = 1                        fib x = fib(x-1) + fib(x-2)                        

可以把清單 7 中的代碼輸入到名為 Fib.hs 的文件中,用 :l fib 裝入它,并輸入 fib(4) 來(lái)運行它,生成序列的第四個(gè)數字。請注意,我不需要聲明保存中間結果的變量。在這個(gè)示例中,可以看到更高級別抽象的示例。如果您的問(wèn)題集恰好適合 Haskell,那么更高級別的抽象就適合您。如果不適合,這種更高級別的抽象將使您陷入麻煩。

可以用與 Fibonacci 序列基本相同的方式對待階乘。x 的階乘就是從 1 到 x 的所有數字的乘積。在 Haskell 中,可以定義一個(gè)計算階乘的函數,如清單 8 所示:


清單 8. 計算階乘
factorial 1 = 1                        factorial x = x * factorial(x-1)                        

對列表的遍歷也采用同樣的工作方式。處理列表時(shí),要處理第一個(gè)節點(diǎn),然后處理列表剩下的部分(剩下的也是列表)。清單 9 顯示了計算列表中所有元素之和的一個(gè)遞歸函數:


清單 9. 計算數字列表的總和
sum [] = 0                        sum (h:t) = h + sum(t)                        

如果您以前沒(méi)見(jiàn)過(guò)這種模式,那么可能需要一點(diǎn)時(shí)間來(lái)習慣它。第一行說(shuō)明空列表的和是 0。第二行代表的概念在幾乎所有函數性語(yǔ)言中都很普遍。(h:t) 把列表表示成 tuple,列表的頭(包含第一個(gè)元素)在 h 內,列表剩余的元素包含在 t 中。由于尾部遞歸優(yōu)化,這種方式是對列表進(jìn)行迭代的一種非常簡(jiǎn)單的方式。思維過(guò)程與代碼的匹配非常好:做第一件事,剩下的事后面再做;什么都不剩時(shí),就完成了。

用同樣的方式也可以遍歷非常復雜的數據結構。只要多付出一點(diǎn)功夫,就能表達 B 樹(shù) —— B 樹(shù)的每個(gè)節點(diǎn)都容納一個(gè)值和兩個(gè)分支。用 Haskell 表示的簡(jiǎn)單 B 樹(shù)形式如下:

data Tree a = Null | Node (Tree a) a (Tree a)                        

在這個(gè)示例中,data 是構建抽象類(lèi)型的手段。a 是類(lèi)型。它告訴 Haskell:樹(shù)可以可以什么都不包含,也可以是由樹(shù)構成的,樹(shù)后面跟著(zhù)值,后面又跟著(zhù)另一個(gè)樹(shù)。樹(shù)中的每個(gè)節點(diǎn)都有一個(gè)值、一個(gè)左子節點(diǎn)和一個(gè)右子節點(diǎn)。(子節點(diǎn)可以是 null,也可以不為 null。)

遍歷樹(shù)的代碼看起來(lái)與遍歷列表的代碼非常像。如果想要 null 樹(shù)的匯總為 null,典型節點(diǎn)的匯總是左樹(shù)的匯總加上值的匯總和右樹(shù)的匯總,請看清單 10:


清單 10. 遍歷樹(shù)
sum_tree :: Tree Integer -> Integer                        sum_tree Null = 0                        sum_tree (Node left val right) = sum_tree left + val + sum_tree right                        

在清單 10 中,第一行定義了函數使用的類(lèi)型。 sum_tree :: Tree Integer -> Integer 意味著(zhù)函數 sum_tree 要接受一個(gè) IntegerTree 作為參數,并返回 Integer。下兩行代碼指定函數??諛?shù)的匯總是零,其他樹(shù)的匯總是左樹(shù)加上 Integer 的值再加上右樹(shù)的值。

現在可以把它放在 Tree.hs 中,如清單 11 所示:


清單 11. Tree.hs
data Tree a = Null | Node (Tree a) a (Tree a)                        sum_tree :: Tree Integer -> Integer                        sum_tree Null = 0                        sum_tree (Node left val right) = sum_tree left + val + sum_tree right                        t::Tree Integer                        t=Node Null 4 Null                        

在這個(gè)示例中,t::Tree IntegerTree 綁定到一個(gè)類(lèi)型,下一行把 t 綁定到一個(gè)值??梢杂?:l Tree 把清單 11 裝入 Hugs,并輸入 sum_tree t。也可以表示更復雜的樹(shù),例如 Node Null 6 (Node Null 7 Null) 表示代碼一個(gè)右節點(diǎn)的樹(shù)??梢园巡煌臉?shù)放在 t 中,然后再次運行 sum_tree 來(lái)感受一下。(請記住,每次試驗時(shí)都需要重新裝入函數。)







回顧函數性 “限制”

Haskell 能夠很好地處理數據結構。因為把字符串看成是字符的簡(jiǎn)單列表,所以 Haskell 不僅能很好地處理各種形式的文本,您還可以有效地處理樹(shù)、復雜的數學(xué)問(wèn)題以及嵌套結構。函數性語(yǔ)言被頻繁地用來(lái)構建編譯器或者解析語(yǔ)言的工具,因為語(yǔ)言通常是用語(yǔ)法樹(shù)表示的。因為可以在數據結構中包含函數,所以函數性語(yǔ)言構成了元編程的優(yōu)秀平臺。

現在已經(jīng)看到了函數性語(yǔ)言的基礎,接下來(lái)可以開(kāi)始了解,您要如何在沒(méi)有副作用和對狀態(tài)只有有限支持的環(huán)境下生活。正如我在前面提到過(guò)的,單體可以表示狀態(tài)的變化。但是即使用了單體,管理狀態(tài)也是困難的 —— 所以不要嘗試這樣做。相反,可以考慮通過(guò)定義不需要中間狀態(tài)的復合函數來(lái)解決問(wèn)題的方式。不要考慮迭代,而應使用遞歸或以下某個(gè)函數 —— map、filterfold,它們會(huì )把表達式應用到列表的每個(gè)元素。要使用函數性語(yǔ)言,只需要放棄命令式編程的風(fēng)格。學(xué)習用更加函數性的風(fēng)格進(jìn)行編程,有以下好處:

  • 可以用更緊湊的方式表示思想。
  • 通過(guò)避免副作用,可以限制應用程序某些類(lèi)型的 bug 的影響。
  • 通過(guò)減少本地變量,可以讓代碼更具伸縮性。

函數性語(yǔ)言極大地影響了編程的思考方式。多年以來(lái),MIT 的程序員最初使用了 Lisp,因為這種語(yǔ)言能夠有力地幫助程序員學(xué)習如何在更高層次的抽象上工作。

本文僅僅觸及到了函數性語(yǔ)言的皮毛。我鼓勵您下載 Haskell 或其他函數性語(yǔ)言,親自動(dòng)手去體驗它。我猜,它會(huì )改造您對編程的思考方式。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
圖靈社區 : 閱讀 : 帶您走進(jìn)七周七語(yǔ)言的程序世界
Haskell入門(mén) - Delphi,Linux,Python -
函數式編程
編程語(yǔ)言的發(fā)展趨勢及未來(lái)方向:函數式編程
編程語(yǔ)言的發(fā)展趨勢及未來(lái)方向(3)
手把手教你寫(xiě)腳本引擎(一)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久