【北京網(wǎng)站制作】函數(shù)式編程很難 這就是你應(yīng)該學習的理由
  • 更新時間:2024-11-07 02:32:33
  • 網(wǎng)站建設(shè)
  • 發(fā)布時間:1年前
  • 406

函數(shù)式編程很難,這正是你要學習它的原因

本文翻譯自文章Functional Programming Is Hard, That's Why It's Good。

奇怪的是沒有,很少有人每天使用函數(shù)式編程語言。如果您使用Scala、Haskell、Erlang、F# 或Lisp 的某些方言進行編程,很可能沒有公司愿意雇用您。這個行業(yè)的絕大多數(shù)人使用面向?qū)ο蟮木幊陶Z言,如Python、Ruby、Java 或C# ——,他們覺得這些語言很舒服。是的,您可能偶爾會使用一兩個“函數(shù)式語言特性”,例如“塊”,但人們不進行函數(shù)式編程。

然而,多年來,我們一直被教導說函數(shù)式編程語言很好,很棒。我還記得第一次閱讀ESR 關(guān)于學習Lisp 的著名論文時的困惑?;蛟S大多數(shù)人都比較熟悉Paul Graham 的《Beating The Averages》 文章:

使用Lisp 開發(fā)使我們能夠如此快速地迭代我們的開發(fā)周期,有時當競爭對手在一兩天后的新聞發(fā)布會上推出他們的新功能時,我們能夠復制相同的功能。當報道產(chǎn)品發(fā)布會的記者打電話給我們時,我們的產(chǎn)品已經(jīng)具有相同的功能。

那些皈依函數(shù)式編程的人中,一直常見的考慮是:學習這種新的、函數(shù)式的語言“對你有好處”;就像是某些人建議說每天30分鐘的健身房活動會“讓你的身體健康”一樣。但這也同時暗示了這樣做的難度和需要的付出。Lisp語言跟Haskell、Ocaml和Scala語言不同,被認為是出了名的難學,可以說是臭名昭著。優(yōu)雅的人說這是Lisp語言“深度和廣度”的體現(xiàn)。粗俗的人說這是“下流”或“玩學術(shù)”或干脆“不要”。在我看來,它的難易程度與你是否熟悉它有關(guān),而這個難易程度是一個重要的指標:學習這樣一門語言會讓你更有效率,更有能力進行編程。

它給你的初次印象不友善

我7 歲時開始編程,在郊區(qū)漫長而無聊的夏天里,我在祖父的電腦上閑逛。我學習了BASIC 并用它在屏幕上畫了一個彈跳球。我學習了Pascal 并用它編寫了一個通過PC 揚聲器播放音樂的程序。我大約10 歲時學習了C,但直到我上高中時才碰上了我無法逾越的墻。那就是:指針。即使沒有這些該死的指點,我在寫作、閱讀、學習和實踐中也遇到了無數(shù)次失敗。我把祖父的硬盤毀了兩次(一次是不小心),結(jié)果不得不自己重裝操作系統(tǒng)很多次。我失敗了,一次又一次地失敗。

也許你的故事與我的相似,也許完全不同。但是我想幾乎每個學過編程的人都經(jīng)歷過困難。我們在學習了一些基礎(chǔ)知識之后,難免會遇到一些公認的概念障礙,比如“指針”。許多計算機科學教授會在他們的課程中將指針描述為過濾器。如果你想成為一名優(yōu)秀的程序員,你必須了解指針。很少有人能輕易掌握它們。包括我在內(nèi)的大多數(shù)人都需要實踐和示例來理解指針是什么以及它們?yōu)槭裁粗匾?

這種艱難的努力過程并非偶然,而是幾乎普遍存在的現(xiàn)象。指針是一個非常強大且具有基本功能的概念。學習它會讓你成為更好的程序員,并讓你更直觀地思考。即使你使用的語言不提供像指針這樣的特性,數(shù)據(jù)結(jié)構(gòu)和類似于指針的概念也比比皆是。 (北京網(wǎng)出品)

新奇事物

一旦你學會了幾種語言,所有的語言都會開始變得相似。會Python的人學習Ruby可能不會有太多問題,而會Java的人會覺得C#很熟悉。是的,也有驚喜。 Ruby 愛好者在學習Python 時會對它的理解感到驚訝,而Java 用戶會對C# 中的委托感到困惑。再一次,如果你只看一眼它們,它們都是相似的。我可以肯定地說,如果您還沒有學習過Lisp 語言,您會發(fā)現(xiàn)所有Lisp 變體都是相似的。

據(jù)說大多數(shù)人在第一次使用Haskell 或Ocaml 時完全不知所措。見鬼,在Haskell 中連分號都不一樣。這不是語法問題; Haskell 和ML 語言完全基于不同的概念,一種新的語言范式。您需要以不同的方式開發(fā)應(yīng)用程序,以不同的方式組織應(yīng)用程序,并以不同的方式擴展應(yīng)用程序。

許多這些新概念都非常強大。有

kell里的Monads 是跟指針一樣基礎(chǔ)且強大的概念(你很可能在不知道它叫什么的情況下就已經(jīng)使用過它們了)。所以,跟學了Java后再學C#不一樣,有志向?qū)W習函數(shù)式語言的人需要往回走的更遠,去學習更加基礎(chǔ)的概念后才能接下去學習。就像是完全再學習一次指針。并且,就像是當年我們剛開始學習編程一樣,一些很大的概念看起來會讓人迷惑茫然,讓人沮喪,直到你去攻克(以及失敗)它們。

吃下你的藥丸,找到你的藥劑師

盡管不好學,但我堅信,學習這些函數(shù)式編程語言會在職業(yè)上對你有好處。我相信有些人讀到這點時會眼睛翻起來向天看,很難想象出這些monoids 或 monad 會對他們在使用Java或C#時有用處。對我而言,我已經(jīng)不驚奇于由于這樣的思維而阻止他們學習函數(shù)式語言的現(xiàn)象;他們需要學習一種跟指針和遞歸一樣基礎(chǔ)的新概念。他們需要有一種只有專業(yè)人員在完成清晰的商業(yè)目標時才具有的耐心和斗志。很少人能在過了可塑的年齡后還受得了挫折——一次又一次的挫折——否則我們現(xiàn)在都早成專家了,不是嗎?

還有更復雜的東西,有大量的語言和算法研究都是用函數(shù)式語言實施的(尤其是Haskell)。你很容易會被這些不熟悉的概念——例如分類學理論, half-finished abstractions,一些失敗的研究——弄的迷失方向。沒有一個清晰的指導(比如由一個實用主義的作者寫的一本好書),本來已經(jīng)很困難的學習任務(wù)變的更加可怕。

這些疊加起來的復雜因素導致了不出意外的結(jié)果:很多人不情愿在函數(shù)式編程學習中投入時間。很容易理解這種不情愿,“我干嘛不把花在學習這些東西的時間用在實現(xiàn)什么東西上呢?”但這種思路也表明了你永遠不愿意在任何新技術(shù)上浪費時間(只用自己熟悉的)。在一個像軟件技術(shù)這樣日新月異的產(chǎn)業(yè)里,我不認為這是正確的判斷。

眼見為實

學習一種函數(shù)式編程語言最顯而易見的好處是,你能學會這種類型語言中的函數(shù)式概念。它能幫助你的大腦,讓它具有能非常清晰的思考和處理一些驚人的重大概念的能力。這并不是函數(shù)式編程具有魔法;各種語言和范式的出現(xiàn)都是為了應(yīng)對某一特定類別的問題。函數(shù)式編程的殺手锏正是應(yīng)對了當今世界上日益增長的并行性編程和元數(shù)據(jù)編程趨勢。

例如,我們研究一個簡化的、本地版本化的Google著名的MapReduce范例。用函數(shù)式方式描述這種范例是不可思議的清晰簡潔:

  1. mapReducer?data?partitioner?mapper?reducer?= ?
  2. ??????????????let?partitions?=?partitioner?data ?
  3. ??????????????in?reduce?reducer?(map?mapper?partitions)?

讓這樣的代碼支持并行計算或分布式并行計算是輕而易舉的(對于本地并行計算,很多的功能包都支持“pmap”和“preduce“——只需要利用函數(shù)式語言的一些簡單特性)。像maps, partitions, generators, streams, reductions, folds, 已以及 function chaining等概念在各種的函數(shù)式編程語言中都大同小異,所以,任何對Lisp,Haskell,OCaml,甚至帶點函數(shù)式語言特征的語言——Python和Ruby熟悉的人,都會很容易的理解這里面的思想精華。

讓我們花點時間考慮一下,如何用一種面向?qū)ο蟮恼Z言,以一種常見的面向?qū)ο蟮哪J絹砬宄拿枋鲞@種架構(gòu)。至少你需要做的事情是定義用來描述mapper和reducer的聲明。如果你有好奇心,請試著用你喜歡的面向?qū)ο笳Z言描述一個最小化的“面向?qū)ο蟆钡腗apReduce。我發(fā)現(xiàn)那是非常羅嗦的。如果使用Java風格的語言,它會像這樣:

  1. interface?Mapper?{ ?
  2. ???B?map(A?input); ?
  3. ?} ?
  4. ?
  5. ?interface?Reducer?{ ?
  6. ???Y?reduce(X?a,?X?b); ?
  7. ?} ?
  8. ?
  9. ?abstract?class?MapReduce?{ ?
  10. ???private?Mapper?mapper; ?
  11. ???private?Reducer?reducer; ?
  12. ?
  13. ???public?MapReduce(Mapper?map,?Reducer?reduce)?{ ?
  14. ?????//?... ?
  15. ???} ?
  16. ?
  17. ???public?run(SeqenceType?data)?{ ?
  18. ?????//?... ?
  19. ???} ?
  20. ?}?

即使是沒有加入循環(huán)邏輯,這種缺乏函數(shù)式模式中常見的名詞和動詞的使用,使得MapReduce這種技術(shù)很難被定義。這種定義方式幾乎是滑稽可笑的,但它能讓你想到函數(shù)式概念。另外一個好例子是Scala語言如何利用完備的Java Fork/Join 類庫,把它輕松的集成的自己的自有語法中。

各有所求

所以,我鼓勵任何想進步的程序員:請考慮學習一種函數(shù)式語言。Haskell和OCaml都是極好的選擇,F(xiàn)#和Erlang也相當?shù)牟诲e。它們都不好學,但也許這是個好事。努力弄清楚你遇到的復雜的概念,看看是否有其他人正在利用這些概念;經(jīng)常的,你會在尋找這些不熟悉的概念的真正用意的時候?qū)崿F(xiàn)思想上的突破。

當你開始學的時候,請注意,不要過于在意。就像其他任何需要你花時間和精力的事情一樣,過度的在函數(shù)式編程上進行精力上的投資是很危險的。掉進了認知能力的陷阱后你的投資會血本無歸。你很容易會忘掉世界上還有無數(shù)種計算模型,你更容易忘掉有多少種優(yōu)秀的軟件根本沒有使用任何的函數(shù)式概念。

學習的道路會越來越難走,但從另一方面說,在你日常的編程中,你會發(fā)現(xiàn)有越來越多的可以使用的重要概念和模型。對于這樣緊湊的編程風格你會越來越適應(yīng),必然,你也會對如何成為一名更好的軟件工程師有了新的認識。

補充

有不少校對這篇文章的人在看完文章后都問了我一個同樣的問題:“聽起來不錯,大衛(wèi),可是我應(yīng)該學習那種語言呢?”當然,這是他們給我出的難題。

我想,如果你是一個很有經(jīng)驗的程序員,這最能“應(yīng)付”這個問題的答案是:“選一種符合你的需求的”。如果你需要在JVM上工作,選擇Scala或Clojure。如果你想能快速的開發(fā)大型分布式軟件系統(tǒng),選擇Erlang。如果你想要一種具有超強編譯器的超能干活的語言,請選擇Haskell或RCaml。如果你想要一種比Ruby或Python更有能力的原型工具,選擇Scheme。

請記住,我們在這里要做的這些目的是為了實際的技能和自我進步。如果你能騰出時間學這些,就走出你的安逸環(huán)境,挑戰(zhàn)自己。

因為我已經(jīng)學習了Lisp和Erlang,而且使用OCaml做專業(yè)工作,我決定研究一下Haskell,這完全是另外一個世界。我發(fā)現(xiàn)唯一能幫助我參透這種語言的途徑是依賴Learn You A Haskell和 Real World Haskell 這兩本有用的指導材料。這些書寫的非常好,很有價值,而且可以免費在網(wǎng)上找到。如果你想試一下Haskell,這些書可以當作你的尋寶圖。(高端網(wǎng)站建設(shè))

我們專注高端建站,小程序開發(fā)、軟件系統(tǒng)定制開發(fā)、BUG修復、物聯(lián)網(wǎng)開發(fā)、各類API接口對接開發(fā)等。十余年開發(fā)經(jīng)驗,每一個項目承諾做到滿意為止,多一次對比,一定讓您多一份收獲!

本文章出于推來客官網(wǎng),轉(zhuǎn)載請表明原文地址:https://www.tlkjt.com/web/13822.html
推薦文章

在線客服

掃碼聯(lián)系客服

3985758

回到頂部