那些讓碼農(nóng)倍感痛苦的現(xiàn)代編程語言
特定編程語言的優(yōu)缺點(diǎn)是什么?X是我的任務(wù)很好的語言嗎?搜尋"最佳編程語言"將為您提供" Python,Java,JavaScript,C#,C ++,PHP"的標(biāo)準(zhǔn)列表,以及優(yōu)缺點(diǎn)的模糊列表??吹竭@樣的文章會(huì)讓我感到痛苦,他們的作者一定是完全懶惰,缺乏經(jīng)驗(yàn),同時(shí)又缺乏想象力。讓我們深入研究一下,找出真正的缺點(diǎn),而不是什么。
在本文中,我將嘗試對(duì)流行的(而不是那么流行的)現(xiàn)代編程語言進(jìn)行客觀,公正的概述,從最壞到最好的排名。
請(qǐng)記住,沒有一種編程語言可以完美地適合所有可能的用例。一些語言最適合于前端開發(fā),其他語言最適合于后端/ API開發(fā),其他語言則非常適合系統(tǒng)編程。
我將介紹世界上兩個(gè)最常見的語言家族-語言是C衍生的,而語言是ML衍生的。
編程語言只是開發(fā)人員工具箱中的工具。選擇正確的工具來完成這項(xiàng)工作很重要。我真的希望本指南將幫助您選擇最適合您任務(wù)的編程語言。做出正確的選擇可以節(jié)省您數(shù)月(甚至數(shù)年)的開發(fā)工作。
哪些語言特征真正重要?
大多數(shù)其他類似的文章都根據(jù)受歡迎程度和潛在收入等因素進(jìn)行比較。受歡迎程度很少是一個(gè)很好的衡量標(biāo)準(zhǔn),尤其是在軟件領(lǐng)域(盡管大型社區(qū)和生態(tài)系統(tǒng)會(huì)有所幫助)。相反,我將考慮特定語言的優(yōu)點(diǎn)和缺點(diǎn)。
我將使用大拇指(即+1),大拇指朝下或OK(無論好壞)表情符號(hào)來表示特定語言特征的得分。
現(xiàn)在,我們將如何衡量?換句話說,除了語言流行之外,真正重要的是什么?
一、類型系統(tǒng)
許多人按類型系統(tǒng)發(fā)誓。因此,近年來諸如TypeScript之類的語言開始流行。我傾向于同意,類型系統(tǒng)消除了程序中的大量錯(cuò)誤,并使重構(gòu)更加容易。但是,"擁有"類型系統(tǒng)只是故事的一部分。
如果語言具有類型系統(tǒng),那么進(jìn)行類型推斷也非常有用。最好的類型系統(tǒng)能夠推斷大多數(shù)類型,而無需顯式注釋功能簽名。不幸的是,大多數(shù)編程語言僅提供基本的類型推斷。
對(duì)于類型系統(tǒng)來說,支持?jǐn)?shù)字?jǐn)?shù)據(jù)類型也很好(稍后會(huì)詳細(xì)介紹)。
最強(qiáng)大的類型系統(tǒng)支持高級(jí)類型,這是泛型之上的抽象級(jí)別,并允許我們以更高的抽象級(jí)別進(jìn)行編程。
我們還必須記住,人們往往對(duì)類型系統(tǒng)過于重視。有些事情遠(yuǎn)比靜態(tài)類型重要,選擇類型時(shí),類型系統(tǒng)的存在與否并不是唯一的因素。
(1) 學(xué)習(xí)曲線
我們可能擁有完美的編程語言,但是如果新入職的開發(fā)人員可能要花費(fèi)數(shù)月甚至數(shù)年(前期投資)來學(xué)習(xí),它將有什么用?另一方面,某些編程范例需要花費(fèi)數(shù)年才能變得精通。
一門好的語言應(yīng)該適合初學(xué)者,并且不需要花幾年的時(shí)間就能掌握。
(2) 空值
我稱之為我的十億美元錯(cuò)誤。它是1965年創(chuàng)建的空引用。當(dāng)時(shí),我正在設(shè)計(jì)第一個(gè)全面的類型系統(tǒng),用于面向?qū)ο蟮恼Z言中的引用。我的目標(biāo)是確保對(duì)引用的所有使用都絕對(duì)安全,并由編譯器自動(dòng)執(zhí)行檢查。但是我忍不住要插入一個(gè)空引用的誘惑,僅僅是因?yàn)樗苋菀讓?shí)現(xiàn)。這導(dǎo)致了無數(shù)錯(cuò)誤,漏洞和系統(tǒng)崩潰,在最近四十年中可能造成十億美元的痛苦和破壞。
-空引用的發(fā)明者托尼·霍爾(Tony Hoare) |
為什么空引用不好?空引用中斷類型系統(tǒng)。當(dāng)null為默認(rèn)值時(shí),我們將不再依賴編譯器來檢查代碼的有效性。任何可為空的值都是等待爆炸的炸彈。如果我們嘗試使用我們不認(rèn)為可能為空但實(shí)際上為空的值怎么辦?我們得到一個(gè)運(yùn)行時(shí)異常。
我們必須依靠手動(dòng)運(yùn)行時(shí)檢查來確保所處理的值不為null。即使使用靜態(tài)類型的語言,空引用也剝奪了類型系統(tǒng)的許多好處。
實(shí)際上,這種運(yùn)行時(shí)檢查(有時(shí)稱為空防護(hù))是針對(duì)不良語言設(shè)計(jì)的解決方法。他們用樣板亂碼。最糟糕的是,我們無法保證不會(huì)忘記檢查null。
用一種好的語言,應(yīng)該在編譯時(shí)檢查值的缺失或存在。
鼓勵(lì)使用其他機(jī)制處理缺失數(shù)據(jù)的語言將排名更高。
(3) 錯(cuò)誤處理
捕獲異常是處理錯(cuò)誤的一種壞方法。拋出異常是可以的,但僅在例外情況下,程序無法恢復(fù)并且必須崩潰。就像空值一樣,異常會(huì)破壞類型系統(tǒng)。
當(dāng)使用異常作為錯(cuò)誤處理的主要方式時(shí),就無法知道函數(shù)是返回期望值還是崩潰。引發(fā)異常的函數(shù)也是不可能組成的。
顯然,僅僅由于我們無法獲取某些數(shù)據(jù)而導(dǎo)致整個(gè)應(yīng)用程序崩潰是不可能的。但這確實(shí)比我們想要的更經(jīng)常發(fā)生。
一種選擇是手動(dòng)檢查引發(fā)的異常,但是這種方法很脆弱(我們可能會(huì)忘記檢查異常),并且會(huì)增加很多噪音:
如今,有更好的錯(cuò)誤處理機(jī)制,可能的錯(cuò)誤應(yīng)在編譯時(shí)進(jìn)行類型檢查。默認(rèn)情況下不使用例外的語言將排名更高。
(4) 并發(fā)
我們已經(jīng)到了摩爾定律的盡頭,處理器將不會(huì)更快。我們生活在多核CPU時(shí)代,實(shí)際上,任何現(xiàn)代應(yīng)用程序都必須利用多核。
不幸的是,當(dāng)今使用的大多數(shù)編程語言都是在單核計(jì)算時(shí)代設(shè)計(jì)的,根本不具備可在多核上有效運(yùn)行的功能。
幫助并發(fā)的庫是事后的想法,它們只是向最初不是為并發(fā)設(shè)計(jì)的語言添加了創(chuàng)可貼。這并不是真正的良好開發(fā)經(jīng)驗(yàn)。在現(xiàn)代語言中,必須內(nèi)置并發(fā)支持(請(qǐng)考慮使用Go / Erlang / Elixir)。
(5) 不變性
我認(rèn)為,當(dāng)構(gòu)建可變對(duì)象的大對(duì)象圖時(shí),大型面向?qū)ο蟮某绦驎?huì)越來越復(fù)雜。你知道,嘗試?yán)斫獠⒗斡洰?dāng)調(diào)用方法時(shí)會(huì)發(fā)生什么副作用。
— Clojure的創(chuàng)建者Rich Hickey。 |
如今,使用不變的值進(jìn)行編程變得越來越流行。甚至像React這樣的現(xiàn)代UI庫也打算與不可變值一起使用。具有對(duì)不可變數(shù)據(jù)值的一流支持的語言將排名更高。僅僅因?yàn)椴蛔冃韵宋覀兇a中的一整類錯(cuò)誤。
什么是不可變狀態(tài)?簡(jiǎn)而言之,它是不變的數(shù)據(jù)。就像大多數(shù)編程語言中的字符串一樣。例如,大寫字符串永遠(yuǎn)不會(huì)更改原始字符串-始終會(huì)返回一個(gè)新字符串。
不變性進(jìn)一步推動(dòng)了這一想法,并確保一切都沒有改變??倳?huì)返回一個(gè)新數(shù)組,而不是更改原始數(shù)組。更新用戶名?將返回一個(gè)新的用戶對(duì)象,并更新其名稱,同時(shí)保留原始對(duì)象。
處于不可變狀態(tài)時(shí),不會(huì)共享任何內(nèi)容,因此我們不再需要擔(dān)心線程安全性的復(fù)雜性。不變性使我們的代碼易于并行化。
不改變?nèi)魏螤顟B(tài)的函數(shù)稱為純函數(shù),它們很容易測(cè)試和推理。使用純函數(shù)時(shí),我們不必?fù)?dān)心函數(shù)之外的任何事情。只需專注于正在使用的這一函數(shù),而忽略其他所有函數(shù)。你可能可以想象,開發(fā)變得多么容易(與OOP相比,必須牢記整個(gè)對(duì)象圖)。
(6) 生態(tài)系統(tǒng)/工具
語言可能不是很好,但是它可能具有龐大的生態(tài)系統(tǒng),因此很有吸引力。訪問優(yōu)質(zhì)的庫可以節(jié)省一個(gè)月(甚至幾年)的開發(fā)工作。
我們已經(jīng)看到JavaScript和Python等語言會(huì)發(fā)生這種情況。
(7) 速度
語言的編譯速度如何?程序啟動(dòng)速度有多快?運(yùn)行時(shí)性能如何?所有這些都很重要,并將列入排名。
(8) 年齡
盡管有一些例外,但通常來說,較新的語言會(huì)比較舊的語言更好。僅僅因?yàn)楦碌恼Z言可以從其前輩的錯(cuò)誤中學(xué)習(xí)。
二、C ++

讓我們從最壞的情況入手,這可能是計(jì)算機(jī)科學(xué)中最大的錯(cuò)誤之一,C ++。是的,C ++不被認(rèn)為是一種嶄新的現(xiàn)代編程語言。但是今天它仍在廣泛使用,必須將其包括在列表中。
語言家族:C.
(1) 語言功能

C ++是一種可怕的語言……而且將項(xiàng)目限制為C意味著人們不會(huì)用任何愚蠢的"對(duì)象模型" c&@ p弄亂事情。— Linux的創(chuàng)建者Linus Torvalds。
C ++具有許多功能。它嘗試做所有事情,同時(shí)又不擅長(zhǎng)任何特定的事情。C ++具有g(shù)oto,指針,引用,OOP,運(yùn)算符重載和許多其他非生產(chǎn)性功能。
為什么C ++如此糟糕?我認(rèn)為,最大的原因是它的年齡。C ++是在1979年設(shè)計(jì)的很早的時(shí)候。當(dāng)時(shí)的設(shè)計(jì)師缺乏經(jīng)驗(yàn),也不知道該關(guān)注什么。當(dāng)時(shí)添加的功能似乎是個(gè)好主意。該語言非常流行,這意味著添加了許多功能來支持各種用例(創(chuàng)建更大的功能混亂)。
(2) 速度
C ++因其編譯時(shí)間慢而臭名昭著。比Java慢得多,不如Scala。
但是,運(yùn)行時(shí)性能以及啟動(dòng)時(shí)間都很好。
(3) 生態(tài)/工具

以上推文很有意義。C ++編譯器
(4) 垃圾收集
我曾希望可以選擇啟用的垃圾收集器將成為C ++ 0x的一部分,但是存在足夠的技術(shù)問題……
-C ++的創(chuàng)建者Bjarne Stroustrup |
垃圾回收從未添加到C ++中。手動(dòng)內(nèi)存管理極易出錯(cuò)。開發(fā)人員必須擔(dān)心手動(dòng)釋放和分配內(nèi)存。我將永遠(yuǎn)不會(huì)錯(cuò)過使用非垃圾收集語言的日子,如今在垃圾收集語言中很容易避免許多錯(cuò)誤。
(5) attempt失敗的面向?qū)ο缶幊虈L試
我發(fā)明了術(shù)語"面向?qū)ο?quot;,可以告訴您我沒有C ++。
-Alan Kay,面向?qū)ο缶幊痰陌l(fā)明者。 |
OOP出現(xiàn)于60年代后期,是C ++工作開始時(shí)的一項(xiàng)很酷的新技術(shù)。不幸的是,C ++在實(shí)現(xiàn)OOP時(shí)犯了一些關(guān)鍵錯(cuò)誤(與Smalltalk等語言不同),這使一個(gè)好主意變成了一場(chǎng)噩夢(mèng)。
與Java相比,C ++的一件好事是C ++中的OOP至少是可選的。
(6) 學(xué)習(xí)曲線
> Mercurial_Rhombus on Reddit
C ++是一種復(fù)雜的低級(jí)語言,沒有自動(dòng)內(nèi)存管理。由于其功能膨脹,初學(xué)者不得不花很多時(shí)間學(xué)習(xí)該語言。
(7) 并發(fā)
C ++是在單核計(jì)算時(shí)代設(shè)計(jì)的,在過去的十年中僅添加了基本的并發(fā)機(jī)制。
(8) 錯(cuò)誤處理
捕獲/拋出錯(cuò)誤是首選的錯(cuò)誤處理機(jī)制。
(9) 不變性
沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(10) 空值
在C ++中,所有引用都是可為空的。
(11) 結(jié)論0.5星
最初旨在成為C的更好版本的C ++確實(shí)未能實(shí)現(xiàn)目標(biāo)。
C ++的最佳用途可能是系統(tǒng)編程。但是,鑒于存在更好,更現(xiàn)代的替代方案(Rust and Go),C ++甚至不應(yīng)該用于此。我認(rèn)為C ++毫無優(yōu)勢(shì),請(qǐng)隨時(shí)證明我是錯(cuò)的。
C ++,你該走了。
三、Java
自從MS-DOS以來,Java是計(jì)算機(jī)行業(yè)中最令人困擾的事情。
-Alan Kay,面向?qū)ο缶幊痰陌l(fā)明者。 |
自1995年首次出現(xiàn)以來,Java比C ++年齡小16歲。Java是一種簡(jiǎn)單得多的語言,這可能有助于其流行。
語言家族:C.
(1) 垃圾收集
Java提供的優(yōu)于C ++的最大好處之一是垃圾收集,垃圾收集本身消除了許多錯(cuò)誤。
(2) 生態(tài)
Java已經(jīng)存在了很長(zhǎng)時(shí)間,并且它具有一個(gè)龐大的用于后端開發(fā)的生態(tài)系統(tǒng),從而大大減少了開發(fā)工作。
(3) 面向?qū)ο笳Z言
在這里,我不會(huì)深入探討OOP的缺點(diǎn),有關(guān)更詳細(xì)的分析,可以閱讀我的其他文章《面向?qū)ο缶幊?mdash;萬億美元災(zāi)難》。
相反,我只是引用一些計(jì)算機(jī)科學(xué)領(lǐng)域最杰出的人,以得到他們對(duì)OOP的看法:
很抱歉,我很久以前就為該主題創(chuàng)造了"對(duì)象"一詞,因?yàn)樗乖S多人專注于較小的想法。大想法是消息傳遞。 -OOP的發(fā)明者艾倫·凱(Alan Kay) |
艾倫·凱(Alan Kay)是對(duì)的,主流的OOP語言專注于錯(cuò)誤的事物(類和對(duì)象),而忽略了消息傳遞。值得慶幸的是,現(xiàn)代語言正確地實(shí)現(xiàn)了這個(gè)想法(Erlang / Elixir)。
使用受OOP影響的編程語言,計(jì)算機(jī)軟件變得更冗長(zhǎng),可讀性更差,描述性更強(qiáng),更難修改和維護(hù)。
—理查德·曼斯菲爾德(Richard Mansfield) |
使用過OOP語言(例如Java或C#)并具有使用非OOP語言的經(jīng)驗(yàn)的任何人都可以聯(lián)系。
(4) 速度
顯然,Java在Java虛擬機(jī)之上運(yùn)行,而Java虛擬機(jī)的啟動(dòng)時(shí)間很慢。我已經(jīng)看到,在JVM上運(yùn)行的程序需要30秒甚至更長(zhǎng)的時(shí)間才能啟動(dòng),這對(duì)于現(xiàn)代的云原生程序來說是不可接受的。
在較大的項(xiàng)目上,編譯速度很慢,這極大地影響了開發(fā)人員的生產(chǎn)力(盡管沒有Scala那樣糟糕)。
從好的方面來說,JVM的運(yùn)行時(shí)性能確實(shí)不錯(cuò)。
(5) 學(xué)習(xí)曲線
盡管Java是一種相當(dāng)簡(jiǎn)單的語言,但它對(duì)面向?qū)ο缶幊痰年P(guān)注使真正變得很難??梢暂p松編寫一個(gè)簡(jiǎn)單的程序。但是,知道如何編寫可靠且可維護(hù)的面向?qū)ο蟠a可能要花十年的時(shí)間。
(6) 并發(fā)
Java是在單核計(jì)算時(shí)代設(shè)計(jì)的,并且像C ++一樣,僅具有基本的并發(fā)支持。
(7) 空值
在Java中,所有引用都是可為空的。
(8) 錯(cuò)誤處理
捕獲/拋出錯(cuò)誤是首選的錯(cuò)誤處理機(jī)制。
(9) 不變性
沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(10) 結(jié)論 1星
Java出現(xiàn)時(shí)是一種不錯(cuò)的語言。太糟糕了,Java(與Scala不同)一直只專注于OOP。該語言非常冗長(zhǎng),并且受樣板代碼的影響很大。
Java退休的時(shí)候到了。
四、C#
從根本上講,C#和Java之間幾乎沒有什么區(qū)別(因?yàn)镃#的早期版本實(shí)際上是Java的Microsoft實(shí)現(xiàn))。
C#與Java共享大多數(shù)缺點(diǎn)。C#于2000年首次出現(xiàn),但比Java年齡小5歲,并且已經(jīng)從Java的錯(cuò)誤中學(xué)到了一些東西。
語言家族:C.
(1) 語法
C#語法一直領(lǐng)先于Java。C#比樣板代碼遭受的痛苦更少。盡管C#是一種OOP語言,但它在冗長(zhǎng)的方面更為重要。很高興看到C#語法在每個(gè)版本中都得到了改進(jìn),并增加了諸如表達(dá)式強(qiáng)健的函數(shù)成員,模式匹配,元組等功能。
(2) 面向?qū)ο笳Z言
就像Java一樣,C#主要關(guān)注OOP。再一次,我不會(huì)在這里花太多時(shí)間試圖說服OOP的缺點(diǎn),我只想引用一些計(jì)算機(jī)科學(xué)領(lǐng)域的杰出人物。
我認(rèn)為缺乏可重用性的是面向?qū)ο蟮恼Z言,而不是函數(shù)語言。因?yàn)槊嫦驅(qū)ο笳Z言的問題在于它們擁有了它們所伴隨的所有隱式環(huán)境。你想要香蕉,但是得到的是一只大猩猩,拿著香蕉和整個(gè)叢林。
— Erlang的創(chuàng)建者Joe Armstrong |
我必須同意Joe Armstrong的觀點(diǎn),與函數(shù)(甚至命令性)代碼相比,重用面向?qū)ο蟮拇a非常困難。
提供面向?qū)ο蟮某绦蜃鳛檎_程序的替代方案…… —計(jì)算機(jī)科學(xué)的先驅(qū)Edsger W. Dijkstra |
在我整個(gè)職業(yè)生涯中都使用過OOP和非OOP語言之后,我不得不同意與非OOP代碼相比,OOP代碼更難正確。
(3) 多范式?
C#聲稱是一種多范式語言。特別是,C#聲稱支持函數(shù)編程。我必須不同意,僅僅支持一流的函數(shù)還不足以使一種語言稱為函數(shù)式。
語言應(yīng)具有哪些功能?至少,對(duì)不可變數(shù)據(jù)結(jié)構(gòu),模式匹配,函數(shù)組合的管道運(yùn)算符,代數(shù)數(shù)據(jù)類型的內(nèi)置支持。
(4) 并發(fā)
C#是在單核計(jì)算時(shí)代創(chuàng)建的,就像Java一樣,它僅具有基本的并發(fā)支持。
(5) 空值
在C#中,所有引用都是可為空的。
(6) 錯(cuò)誤處理
捕獲/拋出錯(cuò)誤是首選的錯(cuò)誤處理機(jī)制。
(7) 不變性
沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(8) 結(jié)論 1.5星
我在C#的職業(yè)生涯中花費(fèi)了大量時(shí)間,并且總是對(duì)這種語言感到沮喪。與Java一樣,我建議您尋找更現(xiàn)代的替代方案。它是相同的Java,但語法更現(xiàn)代。
不幸的是,關(guān)于C#并沒有什么"尖銳"的東西。
Python
自1991年首次出現(xiàn)以來,Python是一門古老的語言。與JavaScript一起,Python是世界上最受歡迎的語言之一。
語言家族:C.
(1) 生態(tài)
Python幾乎有任何庫。與JavaScript不同,Python無法用于前端Web開發(fā),但是Python可以輕松地構(gòu)建大量的數(shù)據(jù)科學(xué)庫。
(2) 學(xué)習(xí)努力
Python是一種非常簡(jiǎn)單的語言,初學(xué)者可以在幾周內(nèi)掌握它們。
(3) 類型系統(tǒng)
Python是動(dòng)態(tài)類型的,關(guān)于類型系統(tǒng)沒有太多要說的了。
(4) 速度
Python是一種解釋型語言,以運(yùn)行時(shí)性能而言,它因?yàn)槭亲盥木幊陶Z言之一而臭名昭著。在運(yùn)行時(shí)性能至關(guān)重要的情況下,使用Cython代替普通的Python可能是一個(gè)很好的解決方案。
與本地語言相比,Python的啟動(dòng)速度也很慢。
(5) 工具
在將Python和其他現(xiàn)代語言一起使用后,很難不對(duì)Python的依賴項(xiàng)管理感到失望。pip,pipenv,virtualenv等。相比之下,JavaScript中的NPM是您唯一需要的工具。
(6) 并發(fā)
創(chuàng)建Python時(shí)并沒有考慮到并發(fā)性,它僅具有基本的并發(fā)支持。
(7) 空值
在Python中,所有引用都是可為空的。
(8) 錯(cuò)誤處理
捕獲/拋出錯(cuò)誤是首選的錯(cuò)誤處理機(jī)制。
不變性
沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(9) 結(jié)論 2星
真的很不幸,Python沒有對(duì)函數(shù)式編程的適當(dāng)支持。函數(shù)式編程非常適合于數(shù)據(jù)科學(xué)試圖解決的問題。即使對(duì)于諸如網(wǎng)絡(luò)抓取之類的非常Python的任務(wù),函數(shù)式語言(例如Elixir)也更合適。
我不建議將Python用于大型項(xiàng)目,因?yàn)樵撜Z言在構(gòu)建時(shí)并未考慮到嚴(yán)格的軟件工程。
當(dāng)沒有其他替代方法可用時(shí),Python不應(yīng)用于數(shù)據(jù)科學(xué)以外的其他任何用途。在數(shù)據(jù)科學(xué)領(lǐng)域,Julia似乎是Python的一個(gè)很好的現(xiàn)代替代品,盡管它的生態(tài)系統(tǒng)還不如Python成熟。
Rust
Rust是一種現(xiàn)代的低級(jí)語言,最初被設(shè)計(jì)為C ++的替代語言。
語言家族:C.
(1) 速度
Rust從一開始就被設(shè)計(jì)為快速。Rust程序的編譯比Go程序的編譯花費(fèi)更長(zhǎng)的時(shí)間。Rust程序的運(yùn)行時(shí)性能比Go快一點(diǎn)。
(2) 空值
我們列表中的第一種語言,帶有現(xiàn)代的null選擇!Rust沒有null或nil值,Rust開發(fā)人員改用Option Pattern。
(3) 錯(cuò)誤處理
Rust采用了現(xiàn)代的功能性方法來處理錯(cuò)誤,并使用專用的Result類型來表示可能失敗的操作。它與上面的選項(xiàng)非常相似,但是None情況現(xiàn)在也有一個(gè)值。
(4) 內(nèi)存管理
Rust是我們列表中唯一沒有垃圾回收的現(xiàn)代語言。這迫使開發(fā)人員考慮進(jìn)行低級(jí)內(nèi)存管理,并使開發(fā)人員的工作效率下降。
(5) 并發(fā)
由于缺乏垃圾收集,因此在Rust中并發(fā)非常困難。開發(fā)人員必須擔(dān)心諸如裝箱和固定之類的事情,這些事情通常會(huì)以垃圾回收語言自動(dòng)完成。
(6) 不變性
Rust沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(7) 低級(jí)語言
作為一種低級(jí)語言,Rust中的開發(fā)人員生產(chǎn)力無法達(dá)到其他高級(jí)語言中的水平。這也使學(xué)習(xí)努力變得更加困難。
(8) 結(jié)論 2星
Rust非常適合系統(tǒng)編程。盡管它比Go更復(fù)雜,但它提供了強(qiáng)大的類型系統(tǒng)。Rust為空值提供了一種現(xiàn)代的替代方法,并提供了一種處理錯(cuò)誤的現(xiàn)代方法。
為什么Rust仍然排名低于TypeScript和JavaScript?它是為系統(tǒng)編程設(shè)計(jì)的低級(jí)語言。Rust并非非常適合后端/ Web API開發(fā)。它缺少垃圾收集,并且不內(nèi)置對(duì)不變性的支持。
TypeScript
TypeScript是一種js編譯語言。它的主要目標(biāo)是通過向JavaScript添加靜態(tài)類型來制作"更好的JavaScript"。就像JavaScript一樣,TypeScript被用于前端和后端開發(fā)。
TypeScript是由設(shè)計(jì)C#的同一人Anders Hejlsberg設(shè)計(jì)的。TypeScript代碼感覺非常CSharp,從根本上講,可以將其視為瀏覽器的C#。
語言家族:C.
(1) JavaScript的超集
是的,JavaScript的超集對(duì)TypeScript的采用起到了很大的幫助。畢竟,很多人已經(jīng)知道JavaScript。
但是,作為JavaScript的超集更為不利。這意味著TypeScript承載了所有JavaScript包。它受到JavaScript中所有錯(cuò)誤的設(shè)計(jì)決策的限制。
例如,有多少人喜歡this關(guān)鍵字?可能沒人,但是TypeScript故意決定保留它。
類型系統(tǒng)有時(shí)真的很奇怪嗎?
- [] == ![]; // -> true
- NaN === NaN; // -> false
換句話說,TypeScript具有JavaScript的所有缺點(diǎn)。成為一門糟糕的語言的超集并不能證明它是好的。
(2) 生態(tài)
TypeScript可以訪問整個(gè)JavaScript生態(tài)系統(tǒng),這是巨大的。巨大的好處。與特別是與其他語言(例如Python)相比,Node Package Manager非常令人愉快。
缺點(diǎn)是并非所有JavaScript庫都具有可用的TypeScript聲明。Rambda,一成不變。
(3) 類型系統(tǒng)
我對(duì)TypeScript中的類型系統(tǒng)不太滿意。
從好的方面來說,它甚至支持?jǐn)?shù)值數(shù)據(jù)類型(區(qū)分聯(lián)合)
TypeScript語法不如功能語言更好。事后考慮,在TypeScript 2.0中添加了有區(qū)別的聯(lián)合。在此開關(guān)中,我們將匹配容易出錯(cuò)的字符串,如果我們錯(cuò)過了情況,編譯器將不會(huì)發(fā)出警告。
TypeScript僅提供基本的類型推斷。另外,在使用TypeScript時(shí),你會(huì)發(fā)現(xiàn)使用頻率比你想要的更多。
(4) 空值
TypeScript 2.0添加了對(duì)非空類型的支持,可以選擇使用–strictNullChecks編譯器標(biāo)志啟用它。但。使用非空類型進(jìn)行編程不是默認(rèn)設(shè)置,并且在TypeScript中不視為慣用語言。
(5) 錯(cuò)誤處理
在TypeScript中,錯(cuò)誤是通過引發(fā)/捕獲異常來處理的。
(6) JS新功能
JavaScript比TypeScript更快地支持酷炫的新功能。使用Babel,甚至可以在JavaScript中啟用實(shí)驗(yàn)性功能,而TypeScript則無法實(shí)現(xiàn)。
(7) 不變性
在TypeScript中處理不可變數(shù)據(jù)結(jié)構(gòu)比在JavaScript中要差得多。盡管JavaScript開發(fā)人員可以使用有助于實(shí)現(xiàn)不變性的庫,但TypeScript開發(fā)人員通常必須依賴于本機(jī)數(shù)組/對(duì)象散布運(yùn)算符(寫時(shí)復(fù)制):
不幸的是,本地傳播運(yùn)算符不會(huì)執(zhí)行深層復(fù)制,而手動(dòng)傳播深層對(duì)象很麻煩。復(fù)制大型數(shù)組/對(duì)象也不利于性能。
TypeScript中的readonly關(guān)鍵字很好,它使屬性不可變。但是,要支持正確的不可變數(shù)據(jù)結(jié)構(gòu)還有很長(zhǎng)的路要走。
JavaScript具有用于處理不可變數(shù)據(jù)的良好庫(例如Rambda / Immutable.js)。但是,使此類庫與TypeScript類型系統(tǒng)一起使用可能非常棘手。
(8) TypeScript和React — 地獄般的匹配嗎?
用JavaScript [和TypeScript]處理不可變數(shù)據(jù)要比用Clojure這樣的語言處理困難。
-直接來自React文檔 |
延續(xù)先前的缺點(diǎn),如果你正在進(jìn)行前端Web開發(fā),那么你很可能正在使用React。
未為TypeScript創(chuàng)建React。最初,React是針對(duì)功能性語言編寫的(稍后會(huì)詳細(xì)介紹)。編程范例之間存在沖突-TypeScript是OOP優(yōu)先,而React是功能優(yōu)先。
React希望其props(即函數(shù)參數(shù))是不可變的,而TypeScript沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的適當(dāng)內(nèi)置支持。
TypeScript通過JavaScript提供給React開發(fā)的唯一真正好處是,不必?fù)?dān)心PropTypes。
(9) 是TypeScript還是Hypescript?
TypeScript只是一種炒作嗎?由你決定。我認(rèn)為是這樣。它的最大好處是可以訪問整個(gè)JavaScript生態(tài)系統(tǒng)。
為什么HypeScript如此受歡迎?Java和C#受歡迎的原因相同-得到數(shù)十億公司的龐大營(yíng)銷預(yù)算的支持。
(10) 結(jié)論 2星
盡管通常認(rèn)為TypeScript是"更好的JavaScript",但我認(rèn)為它比JavaScript低。它提供的超過JavaScript的好處被高估了,特別是對(duì)于使用React進(jìn)行前端Web開發(fā)。
TypeScript確實(shí)無法通過保留JavaScript的所有不良部分來交付,實(shí)際上無法繼承JavaScript中數(shù)十年的不良設(shè)計(jì)決策。
Go
Go旨在幫助提高多核處理器和大型代碼庫時(shí)代的編程效率。Go的設(shè)計(jì)師主要是因?yàn)樗麄儽舜瞬幌矚gC ++,當(dāng)時(shí)在Google廣泛使用了C ++。
語言家族:C.
(1) 并發(fā)
并發(fā)是Go的"殺手級(jí)"功能,Go是從頭開始為并發(fā)而構(gòu)建的。就像Erlang / Elixir一樣,Go遵循并發(fā)的消息模型。不幸的是,Go中的goroutine無法提供與Erlang / Elixir進(jìn)程相同的容錯(cuò)功能。換句話說,goroutine中的異常將導(dǎo)致整個(gè)程序崩潰,而Elixir進(jìn)程中的異常將導(dǎo)致該程序崩潰。
(2) 速度
Google創(chuàng)建Go的主要原因之一是編譯速度。甚至有個(gè)笑話," Google在等待C ++代碼編譯的同時(shí)就創(chuàng)建了Go"。
Go是一種非常快速的語言。Go程序的啟動(dòng)時(shí)間非常快。Go可以編譯為本機(jī)代碼,因此其運(yùn)行速度也非常出色。
(3) 學(xué)習(xí)努力
Go是一種簡(jiǎn)單的語言,有一定的編程經(jīng)驗(yàn)的人大概一個(gè)月就能學(xué)到一門。
(4) 錯(cuò)誤處理
Go不支持例外,而是Go使開發(fā)人員明確處理可能的錯(cuò)誤。與Rust類似,Go返回兩個(gè)值-調(diào)用結(jié)果和潛在錯(cuò)誤。如果一切順利,那么錯(cuò)誤將為零。
(5) 沒有面向?qū)ο蟮木幊?/p>
盡管有些人可能會(huì)不同意,但我個(gè)人認(rèn)為缺少OOP功能是一個(gè)很大的優(yōu)勢(shì)。
重復(fù)Linus Torvalds:
C ++是一種可怕的[面向?qū)ο骫語言…而且將你的項(xiàng)目限制為C意味著人們不會(huì)用任何愚蠢的“對(duì)象模型”。 — Linux的創(chuàng)建者Linus Torvalds |
Linus Torvalds以對(duì)C ++和OOP的公開批評(píng)而聞名。他100%正確的一件事是限制程序員他們可以做出的選擇。實(shí)際上,程序員選擇的次數(shù)越少,代碼的彈性就越大。
在我看來,Go故意省略了許多OOP功能,以免重復(fù)C ++的錯(cuò)誤。
(6) 生態(tài)
一些標(biāo)準(zhǔn)庫確實(shí)很笨。它的很大一部分與Go本身返回帶外錯(cuò)誤的哲學(xué)是不一致的(例如,它們?yōu)樗饕皇?int,error)返回像-1的值),而其他則依賴于全局狀態(tài),例如flag和網(wǎng)絡(luò)/ http。
Go的標(biāo)準(zhǔn)庫中缺乏標(biāo)準(zhǔn)化。例如,某些庫在發(fā)生錯(cuò)誤返回(int,error)的情況下,其他庫則返回諸如-1的值,而其他庫則依賴于全局狀態(tài)(如flag)。
生態(tài)系統(tǒng)遠(yuǎn)沒有JavaScript大。
(7) 類型系統(tǒng)

幾乎每種現(xiàn)代編程語言都有一種或另一種形式的泛型(包括可怕的C#/ Java,甚至C ++都有模板)。泛型允許開發(fā)人員針對(duì)不同類型重用函數(shù)實(shí)現(xiàn)。如果沒有泛型,則必須分別為整數(shù),雙精度數(shù)和浮點(diǎn)數(shù)分別實(shí)現(xiàn)add函數(shù),從而導(dǎo)致大量代碼重復(fù)。換句話說,Go中缺少泛型會(huì)導(dǎo)致大量重復(fù)代碼。有人說," Go"是" Go寫一些樣板"的縮寫
(8) 空值
不幸的是,數(shù)十年來,更安全的替代方法已經(jīng)出現(xiàn),Go語言包含了空值。
(9) 不變性
Go沒有對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持。
(10) 結(jié)論 2.5星
Go不是一種好語言。不算太差;只是不好。我們必須謹(jǐn)慎使用不好的語言,因?yàn)槿绻覀儾恢?jǐn)慎,在接下來的20年中,我們可能最終會(huì)陷入困境。
-雅格(Will Yager)的《為什么Go不好》 |
如果你不是Google,并且沒有類似Google的用例,那么Go可能不是一個(gè)好選擇。Go是最適合系統(tǒng)編程的一種簡(jiǎn)單語言。對(duì)于API開發(fā),Go不是一個(gè)好的選擇(原因是因?yàn)橛泻芏喔玫倪x擇可用,稍后再介紹)。
我認(rèn)為總體而言,Go是一個(gè)比Rust更好的選擇(盡管類型系統(tǒng)較弱)。它是一種簡(jiǎn)單的語言,非???,易于學(xué)習(xí)并且具有出色的并發(fā)功能。是的,Go成功實(shí)現(xiàn)了成為"更好的C ++"的設(shè)計(jì)目標(biāo)。
(11) 最佳系統(tǒng)語言獎(jiǎng)
最佳系統(tǒng)語言獎(jiǎng)歸Go。毫無疑問,Go是系統(tǒng)編程的理想選擇。Go是一種低級(jí)語言,它非常適合該領(lǐng)域,這已被大量使用Go構(gòu)建的成功項(xiàng)目所證實(shí),例如Kubernetes,Docker和Terraform。
JavaScript
作為世界上最受歡迎的編程語言,JavaScript不需要介紹。
是的,這不是一個(gè)錯(cuò)誤。JavaScript確實(shí)排在Rust,TypeScript和Go之上。讓我們找出原因。
語言家族:C.
(1) 生態(tài)
JavaScript的最大好處是其生態(tài)系統(tǒng)。JavaScript正在用于您可以想到的所有內(nèi)容-前端/后端Web開發(fā),CLI編程,數(shù)據(jù)科學(xué)甚至機(jī)器學(xué)習(xí)。JavaScript可能具有一個(gè)庫,可滿足您的所有需求。
(2) 學(xué)習(xí)曲線
JavaScript(以及Python)是最容易學(xué)習(xí)的編程語言之一。一個(gè)人可以在幾周內(nèi)用JavaScript變得富有成效。
(3) 類型系統(tǒng)
就像Python一樣,JavaScript是動(dòng)態(tài)類型的,這里沒有太多要說的了。JavaScript的類型系統(tǒng)有時(shí)可能很奇怪:
(4) 不變性
如TypeScript部分所述,散布運(yùn)算符可能會(huì)降低性能,甚至在復(fù)制對(duì)象時(shí)也不會(huì)執(zhí)行深層復(fù)制。JavaScript缺少對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的內(nèi)置支持,盡管有一些庫可以提供幫助(Ramda / Immutable.js)。
(5) React不是為JavaScript設(shè)計(jì)的
在JavaScript中使用React時(shí),必須使用PropTypes。但是,這也意味著必須維護(hù)PropType,這可能成為噩夢(mèng)。
此外,如果您不小心,可能會(huì)引入細(xì)微的性能問題
這種看上去無辜的代碼可能成為性能的噩夢(mèng),因?yàn)樵贘avaScript中 []!= []。上面的代碼將使HugeList在每次更新時(shí)都重新呈現(xiàn),即使options值沒有更改。在最終無法使用UI之前,這些問題可能會(huì)更加復(fù)雜。
(6) This關(guān)鍵詞
JavaScript的最大反特性可能是this關(guān)鍵字。其行為始終不一致。它是挑剔的,在不同的上下文中可能意味著完全不同的事物。它的行為甚至取決于誰調(diào)用了給定的函數(shù)。通常使用此關(guān)鍵字會(huì)導(dǎo)致難以調(diào)試的細(xì)微而奇怪的錯(cuò)誤。
(7) 并發(fā)
JavaScript使用事件循環(huán)支持單線程并發(fā)。這消除了對(duì)線程同步機(jī)制(如鎖定)的需要。盡管JavaScript并不是在考慮并發(fā)性的情況下構(gòu)建的,但是與大多數(shù)其他語言相比,使用并發(fā)代碼要容易得多。
(8) JS新功能
JavaScript比TypeScript更快地支持酷炫的新功能。使用Babel,甚至可以在JavaScript中啟用實(shí)驗(yàn)功能。
(9) 錯(cuò)誤處理
捕獲/拋出錯(cuò)誤是首選的錯(cuò)誤處理機(jī)制。
(10) 結(jié)論 2.5 星
JavaScript不是一種精心設(shè)計(jì)的語言。JavaScript的初始版本在10天內(nèi)就放在一起了(盡管將來的版本已經(jīng)解決了許多缺點(diǎn))。
盡管有缺點(diǎn),JavaScript是全棧Web開發(fā)的不錯(cuò)選擇。通過適當(dāng)?shù)募o(jì)律和評(píng)價(jià),JavaScript可以成為一門好語言。
函數(shù)式編程==放心
> Photo by Ante Hamersmit on Unsplash
讓我們先繞道而行,然后再繼續(xù)排名。為什么要煩惱函數(shù)式編程?函數(shù)式編程使我們高枕無憂。
是的,函數(shù)式編程可能聽起來很嚇人,但實(shí)際上沒有什么可擔(dān)心的。簡(jiǎn)而言之,函數(shù)式語言做出了許多正確的設(shè)計(jì)決策,而其他語言則做出了錯(cuò)誤的決策。在大多數(shù)情況下,函數(shù)式語言將具有正確的功能:具有代數(shù)數(shù)據(jù)類型支持的功能強(qiáng)大的類型系統(tǒng),無null,錯(cuò)誤處理無異常,內(nèi)置的不變數(shù)據(jù)結(jié)構(gòu),模式匹配,函數(shù)組合運(yùn)算符。
函數(shù)式編程語言有哪些共同的優(yōu)勢(shì)使其在我們的排名中如此高?
(1) 使用純函數(shù)編程
與命令式(主流語言)不同,函數(shù)式編程語言鼓勵(lì)使用純函數(shù)式編程。
什么是純函數(shù)?這個(gè)想法非常簡(jiǎn)單-給定相同的輸入,純函數(shù)將始終返回相同的輸出。例如,2 + 2將始終返回4,這意味著加法運(yùn)算符+是純函數(shù)。
純函數(shù)不允許與外界進(jìn)行交互(進(jìn)行API調(diào)用,甚至無法寫入控制臺(tái))。甚至不允許更改狀態(tài)。這與OOP所采取的方法完全相反,在OOP中,任何方法都可以自由地改變其他對(duì)象的狀態(tài)。
可以很容易地從不純函數(shù)中分辨出純函數(shù)-函數(shù)是不帶參數(shù),還是不返回值?然后,這是一個(gè)不純函數(shù)。
這種方法似乎很局限,可能需要一段時(shí)間才能習(xí)慣。起初,這肯定讓我感到困惑!
純函數(shù)有什么好處?它們非常易于測(cè)試(無需模擬和存根)。關(guān)于純函數(shù)的推理很容易-與OOP不同,無需牢記整個(gè)應(yīng)用程序狀態(tài)。您只需要擔(dān)心當(dāng)前正在使用的功能。
純函數(shù)可以輕松組成。純函數(shù)對(duì)于并發(fā)非常有用,因?yàn)楹瘮?shù)之間沒有共享狀態(tài)。重構(gòu)純函數(shù)是純粹的樂趣-只需復(fù)制和粘貼,無需復(fù)雜的IDE工具。
簡(jiǎn)而言之,純函數(shù)將歡樂帶回到編程中。
函數(shù)式編程鼓勵(lì)使用純函數(shù)-當(dāng)90%以上的代碼庫由純函數(shù)組成時(shí),這很好。一些語言將其極端化,并完全禁止使用非純函數(shù)(這并不總是一個(gè)好主意)。
(2) 不變的數(shù)據(jù)結(jié)構(gòu)
下面的所有功能語言都內(nèi)置了對(duì)不可變數(shù)據(jù)結(jié)構(gòu)的支持。數(shù)據(jù)結(jié)構(gòu)也是持久的。這只是意味著,無論何時(shí)進(jìn)行更改,我們都不必創(chuàng)建整個(gè)結(jié)構(gòu)的深層副本。一次又一次地成像復(fù)制超過100,000個(gè)項(xiàng)目的陣列,這一定很慢,對(duì)吧?
持久數(shù)據(jù)結(jié)構(gòu)無需創(chuàng)建副本,而是簡(jiǎn)單地重用對(duì)舊數(shù)據(jù)結(jié)構(gòu)的引用,同時(shí)添加所需的更改。
(3) 數(shù)值數(shù)據(jù)類型
ADT是一種建模應(yīng)用程序狀態(tài)的強(qiáng)大方法??梢詫⑺鼈円暈轭惞檀嫉拿杜e。我們指定類型可以組成的可能的"子類型",以及其構(gòu)造函數(shù)參數(shù):
上面的"形狀"類型可以是正方形,矩形或圓形。Square構(gòu)造函數(shù)采用單個(gè)int參數(shù)(寬度),Rectangle采用兩個(gè)int參數(shù)(寬度和高度),而Circle采用單個(gè)int參數(shù)(其半徑)。
我不了解你,但我肯定會(huì)使用舊版本,并以功能語言使用ADT。
(4) 模式匹配
所有功能語言都對(duì)模式匹配提供了極大的支持。通常,模式匹配允許人們編寫非常有表現(xiàn)力的代碼。
這是一個(gè)關(guān)于選項(xiàng)(布爾)類型的模式匹配的示例:
相同的代碼,沒有模式匹配:
毫無疑問,模式匹配版本更加富有表現(xiàn)力和簡(jiǎn)潔。
模式匹配還提供了編譯時(shí)的詳盡性保證,這意味著我們將不會(huì)忘記檢查可能的情況。沒有以非功能性語言提供的此類保證。
(5) 空值
函數(shù)式編程語言通常避免使用空引用。而是使用Option模式(類似于Rust):
(6) 錯(cuò)誤處理
通常不建議在功能語言中使用異常。而是使用Result模式(再次,類似于Rust):
要全面了解錯(cuò)誤處理的功能方式,請(qǐng)確保閱讀OCaml中的Composable Error Handling。
(7) 管道前移運(yùn)算符
如果沒有管道前移運(yùn)算符,函數(shù)調(diào)用往往會(huì)變得很嵌套,這使它們的可讀性降低:
函數(shù)式語言具有特殊的管道運(yùn)算符,使該任務(wù)更加容易:
(8) Huskell
語言家族:ML。
(9) 類型系統(tǒng)
沒有比Haskell更強(qiáng)大的文字系統(tǒng)了。顯然,Haskell支持代數(shù)數(shù)據(jù)類型,但它也支持類型類。它的類型檢查器幾乎可以推斷任何東西。
(10) 學(xué)習(xí)曲線
好家伙!為了有效地使用Haskell,必須首先精通類型理論(這不是我在開玩笑),這不是秘密。OOP需要多年的經(jīng)驗(yàn)來編寫體面的代碼,而Haskell則需要投入大量時(shí)間進(jìn)行前期學(xué)習(xí),才能提高生產(chǎn)力。
在Haskell中編寫甚至一個(gè)簡(jiǎn)單的" hello world"程序也需要了解Monads(尤其是IO Monads)。
(11) 社區(qū)
根據(jù)我的經(jīng)驗(yàn),Haskell社區(qū)的學(xué)術(shù)性更高。最近在Haskell庫郵件列表中的帖子開始于:
"在一次私人交流中向我指出,元組函數(shù) x->(x,x)實(shí)際上是對(duì)雙應(yīng)用和一些相關(guān)結(jié)構(gòu)的對(duì)角化的特殊情況。"
它收到了39位漂亮的愛好者答復(fù)。 -Hacker News上的momentoftop |
上面的引用很好地總結(jié)了Haskell社區(qū)。Haskell社區(qū)對(duì)學(xué)術(shù)討論(和類別理論)更感興趣,而不是解決實(shí)際問題。
(12) 函數(shù)純度
正如我們已經(jīng)了解的那樣,純函數(shù)是驚人的。副作用(例如,與外界互動(dòng),包括變異狀態(tài))是程序中大量錯(cuò)誤的原因。作為純函數(shù)式語言,Haskell完全禁止使用它們。這意味著函數(shù)永遠(yuǎn)不能更改任何值,甚至不允許與外界進(jìn)行交互(從技術(shù)上來說,甚至不允許進(jìn)行日志記錄之類的操作)。
當(dāng)然,Haskell提供了與外界交互的解決方法。您可能會(huì)問它如何運(yùn)作?我們提供了一組說明(IO Monad)。這樣的指令可能會(huì)說:讀取鍵盤輸入,然后在某些功能中使用該輸入,然后將結(jié)果打印到控制臺(tái)。然后,語言運(yùn)行庫將獲取此類指令,并為我們執(zhí)行這些指令。我們永遠(yuǎn)不會(huì)執(zhí)行直接與外界交互的代碼。
不惜一切代價(jià)避免成功!
-Haskell的非正式座右銘。 |
實(shí)際上,對(duì)函數(shù)純度的這種關(guān)注顯著增加了抽象的數(shù)量,從而增加了復(fù)雜性,并因此降低了開發(fā)人員的生產(chǎn)率。
(13) 空值
就像Rust一樣,Haskell也沒有null引用。它使用選項(xiàng)模式來表示可能不存在的值。
(14) 錯(cuò)誤處理
盡管某些函數(shù)可能會(huì)引發(fā)錯(cuò)誤,但慣用的Haskell代碼使用的模式類似于Rust中的Result類型。
(15) 不變性
Haskell對(duì)不可變數(shù)據(jù)結(jié)構(gòu)提供一流的支持。
(16) 模式匹配
Haskell具有出色的模式匹配支持。
(17) 生態(tài)
標(biāo)準(zhǔn)庫是一團(tuán)糟,尤其是默認(rèn)的前奏(核心庫)。默認(rèn)情況下,Haskell使用引發(fā)異常的函數(shù)而不是返回選項(xiàng)值(函數(shù)編程的黃金標(biāo)準(zhǔn))。更糟的是,Haskell有兩個(gè)包管理器-Cabal和Stack。
(18) 結(jié)論 3星
核心函數(shù)式編程永遠(yuǎn)不會(huì)成為主流-它需要深刻理解許多高度抽象的概念。
-David Bryant Copeland獲得了四個(gè)更好的軟件設(shè)計(jì)規(guī)則 |
我真的很想喜歡Haskell。不幸的是,Haskell可能會(huì)永遠(yuǎn)局限于學(xué)術(shù)界。Haskell是函數(shù)式編程語言中最糟糕的嗎?我認(rèn)為是你來決定的。
OCaml
OCaml是一種函數(shù)式編程語言。OCaml代表對(duì)象Caml,但是具有諷刺意味的是,很少會(huì)在OCaml中找到使用對(duì)象的人。
OCaml幾乎和Java一樣古老,名稱中的"對(duì)象"部分可能反映了那個(gè)時(shí)代的"對(duì)象"炒作。OCaml只是在Caml離開的地方接機(jī)。
語言家族:ML。
(1) 類型系統(tǒng)
OCaml的類型系統(tǒng)幾乎與Haskell一樣好。最大的缺點(diǎn)是缺少類型類,但它支持仿函數(shù)(高階模塊)。
OCaml是靜態(tài)類型的,其類型推斷幾乎與Haskell一樣好。
(2) 生態(tài)
OCaml社區(qū)很小,這意味著您不會(huì)找到常見用例的高質(zhì)量庫。例如,OCaml缺少一個(gè)不錯(cuò)的Web框架。
與其他語言相比,OCaml庫的文檔非常糟糕。
(3) 工具
工具是一團(tuán)糟。共有三個(gè)包管理員-Opam,Dune和Esy。
OCaml以非常糟糕的編譯器錯(cuò)誤消息而聞名。雖然不是交易破壞者,但這有點(diǎn)令人沮喪,并且會(huì)影響開發(fā)人員的生產(chǎn)率。
(4) 學(xué)習(xí)資源
學(xué)習(xí)OCaml的首選書籍是Real World OCaml。自2013年以來,該書尚未更新,并且許多示例已過時(shí)。使用現(xiàn)代工具不可能遵循本書。
通常,語言教程非常差(與其他語言相比)。它們大多是學(xué)術(shù)課程的講義。
(5) 并發(fā)
" Multicore即將到來的任何一天™️" —在OCaml中并發(fā)地總結(jié)了故事。OCaml開發(fā)人員一直在等待適當(dāng)?shù)亩嗪酥С?,并且似乎不?huì)在不久的將來添加到該語言中。OCaml似乎是唯一缺少適當(dāng)?shù)亩嗪酥С值墓δ苷Z言。
(6) 空值
OCaml沒有空引用,并使用選項(xiàng)模式來表示可能不存在的值。
(7) 錯(cuò)誤處理
慣用的OCaml代碼使用Result類型模式。
(8) 不變性
OCaml對(duì)不可變數(shù)據(jù)結(jié)構(gòu)提供一流的支持。
(9) 模式匹配
OCaml具有出色的模式匹配支持。
(10) 結(jié)論 3星
OCaml是一種很好的函數(shù)式語言。它的主要缺點(diǎn)是并發(fā)支持差,社區(qū)很小(因此生態(tài)系統(tǒng)很小,缺乏學(xué)習(xí)資源)。
鑒于其缺點(diǎn),我不建議在生產(chǎn)中使用OCaml。
· 離開OCaml
Scala
Scala是為數(shù)不多的真正多范例語言之一,對(duì)面向?qū)ο蠛秃瘮?shù)式編程都提供了很好的支持。
語言家族:C.
(1) 生態(tài)
Scala在Java虛擬機(jī)之上運(yùn)行,這意味著它可以訪問龐大的Java庫生態(tài)系統(tǒng)。在后端工作時(shí),這確實(shí)是提高開發(fā)人員工作效率的福音。
(2) 類型系統(tǒng)
Scala可能是唯一具有不健全的類型系統(tǒng)的類型化函數(shù)式語言,并且缺乏適當(dāng)?shù)念愋屯茢?。Scala中的類型系統(tǒng)不如其他函數(shù)式語言那么好。
從好的方面來說,Scala支持更高種類的類型和類型類。
盡管存在缺點(diǎn),但類型系統(tǒng)仍然非常好,因此表示贊許。
(3) 簡(jiǎn)潔/可讀
盡管Scala代碼非常簡(jiǎn)潔,尤其是與Java相比,但代碼可讀性不強(qiáng)。
Scala是實(shí)際上屬于C語言編程語言家族的幾種函數(shù)式語言之一。C系列語言旨在與命令式編程一起使用,而ML系列語言旨在與功能性編程一起使用。因此,在Scala中使用類似C語法的函數(shù)式編程有時(shí)會(huì)感到很奇怪。
Scala中的代數(shù)數(shù)據(jù)類型沒有正確的語法,這會(huì)對(duì)可讀性產(chǎn)生不利影響
就可讀性而言,ML語言的ADT無疑是贏家。
(4) 速度
就編譯速度而言,Scala可能是最差的編程語言之一。一個(gè)簡(jiǎn)單的" hello world"程序可能需要10秒鐘才能在較舊的硬件上進(jìn)行編譯。Scala編譯器不是并發(fā)的(使用單個(gè)內(nèi)核編譯代碼),這不利于編譯速度。
Scala在Java虛擬機(jī)之上運(yùn)行,這意味著程序?qū)⒒ㄙM(fèi)更長(zhǎng)的時(shí)間啟動(dòng)。
(5) 學(xué)習(xí)曲線
Scala具有很多功能,這使得學(xué)習(xí)變得更加困難。就像C ++一樣,該語言具有許多功能。
Scala是最困難的函數(shù)式語言之一(僅次于Haskell)。實(shí)際上,它的易學(xué)性是離開Scala時(shí)公司的首要決定因素。
(6) 不變性
Scala對(duì)不可變數(shù)據(jù)結(jié)構(gòu)(使用案例類)具有一流的支持。
(7) 空值
不利的一面是,Scala支持空引用。從好的方面來看,使用潛在缺失值的慣用方式是使用選項(xiàng)模式(就像其他功能語言一樣)。
(8) 錯(cuò)誤處理
就像其他功能語言一樣,Scala習(xí)慣將Result模式用于錯(cuò)誤處理。
(9) 并發(fā)
Scala在JVM之上運(yùn)行,而JVM并不是真正為并發(fā)而構(gòu)建的。從好的方面來說,Akka工具包非常成熟,并且在JVM上提供了類似于Erlang的并發(fā)。
(10) 模式匹配
Scala具有出色的模式匹配支持。
(11) 結(jié)論 3星
我真的很想喜歡Scala,但我不能。Scala嘗試做太多事情。為了同時(shí)支持OOP和FP,其設(shè)計(jì)人員必須做出很多權(quán)衡。正如俄羅斯諺語所說的那樣:"追趕兩只兔子的人一只都抓不到"。
Elm
Elm是一種功能強(qiáng)大的js編譯語言,主要用于前端Web開發(fā)。
Elm之所以與眾不同,是因?yàn)樗兄Z永遠(yuǎn)不會(huì)出現(xiàn)運(yùn)行時(shí)異常。用Elm編寫的應(yīng)用程序非常強(qiáng)大。
語言家族:ML。
(1) 非常好的錯(cuò)誤消息
Elm編譯器提供了我見過的一些最好的錯(cuò)誤消息,這使該語言甚至對(duì)于初學(xué)者來說也更加容易上手。
(2) 錯(cuò)誤處理
Elm如何處理錯(cuò)誤?就像許多其他功能語言一樣,使用Resultdata類型。
(3) 函數(shù)純度
就像Haskell一樣,Elm是一種純函數(shù)式語言。
Elm是通過消除所有運(yùn)行時(shí)異常來提高生產(chǎn)率,還是通過在所有地方強(qiáng)制執(zhí)行功能純凈來使生產(chǎn)率降低?以我的經(jīng)驗(yàn),在Elm中進(jìn)行任何重大的重構(gòu)都是一場(chǎng)噩夢(mèng),因?yàn)槠渲猩婕按罅康?quot;管道"。
自己決定,但我會(huì)拒絕Elm的這一特性。
(4) 選項(xiàng)過于自以為是
> Quigglez on Reddit
Elm是一種自以為是的語言。到目前為止,使用制表符被視為語法錯(cuò)誤。
Elm對(duì)"永遠(yuǎn)不會(huì)出錯(cuò)"的關(guān)注正在扼殺該語言。最新版本(0.19)引入了一項(xiàng)重大更改,這使得與JavaScript庫的互操作幾乎不可能。當(dāng)然,這樣做的目的是讓人們?cè)贓lm中編寫自己的圖書館,以幫助生態(tài)系統(tǒng)發(fā)展。但是,很少有公司有資源來重新實(shí)現(xiàn)Elm中的所有功能。這使許多人永遠(yuǎn)離開了Elm。
Elm的設(shè)計(jì)師似乎過于專注于函數(shù)純度,將"永無錯(cuò)誤"的想法推向了極致。
(5) React沒有反應(yīng)
Elm利用自己的虛擬DOM,與ReasonML等語言不同,它不使用React。這意味著開發(fā)人員無法訪問為React制作的龐大的庫和組件生態(tài)系統(tǒng)。
(6) 語言發(fā)展
遺憾的是,距離Elm的新版本(0.19.1)已經(jīng)過去了一年多。開發(fā)流程的透明度為零,任何人都無法為開發(fā)做出貢獻(xiàn)。在每一個(gè)主要版本中,Elm都引入了重大更改,這使得某些語言無法使用。一年多來,我們從未真正聽到過其創(chuàng)建者的任何消息。我們甚至都不知道他是否仍在全職從事Elm。到現(xiàn)在,該語言可能實(shí)際上已經(jīng)消失了。
(7) 模式匹配
Elm有很好的模式匹配支持。
(8) 不變性
Elm對(duì)不可變數(shù)據(jù)結(jié)構(gòu)提供一流的支持。
(9) 空值
Elm不支持可為空的引用,就像其他函數(shù)式語言一樣,它使用Option模式。
(10) 結(jié)論 3.5星
Elm是一門出色的語言。不幸的是,它似乎沒有未來。但這可能是進(jìn)入函數(shù)式編程的好方法。
F#
F#可以總結(jié)為.NET的OCaml。它的語法與OCaml非常相似,只是有一些細(xì)微的差別。F#于2005年首次出現(xiàn),是一種非常成熟的語言,具有出色的工具和豐富的生態(tài)系統(tǒng)。
語言家族:ML。
(1) 類型系統(tǒng)
類型系統(tǒng)的唯一缺點(diǎn)是缺少高級(jí)類型。類型系統(tǒng)仍然非常牢固,編譯器能夠推斷出幾乎所有內(nèi)容。F#對(duì)ADT具有適當(dāng)?shù)闹С帧?/p>
(2) 功能性,但不純粹
與Haskell / Elm不同,F(xiàn)#非常實(shí)用,并且不強(qiáng)制執(zhí)行函數(shù)純度。
(3) 學(xué)習(xí)資源
F#有一些非常好的學(xué)習(xí)資源,可能與Elixir相當(dāng)。
(4) 學(xué)習(xí)努力
F#是最容易使用的函數(shù)式語言之一。
(5) 生態(tài)
F#社區(qū)很小,與Elixir等語言不同,它根本沒有相同的強(qiáng)大庫。
(6) #C#互操作
從好的方面來說,F(xiàn)#可以訪問整個(gè).NET / C#生態(tài)系統(tǒng)。與現(xiàn)有C#代碼互操作確實(shí)很好。
(7) 并發(fā)
F#在CLR之上運(yùn)行,它沒有Elixir從Erlang VM中獲得的同樣出色的并發(fā)支持(稍后會(huì)詳細(xì)介紹)。
(8) 空值
F#代碼中通常不使用空值。它使用選項(xiàng)模式來表示可能不存在的值。
(9) 錯(cuò)誤處理
慣用的F#代碼使用Result模式進(jìn)行錯(cuò)誤處理。
(10) 不變性
F#對(duì)不可變數(shù)據(jù)結(jié)構(gòu)具有一流的支持。
(11) 模式匹配
F#具有強(qiáng)大的模式匹配支持。
(12) 結(jié)論 4星
F#是一種非??煽康木幊陶Z言,具有非常好的類型系統(tǒng)。對(duì)于Web API開發(fā),它幾乎與Elixir一樣好(稍后會(huì)詳細(xì)介紹)。但是,F(xiàn)#的問題不是它所擁有的,而是它所沒有的。為了與Elixir進(jìn)行比較,其并發(fā)功能,豐富的生態(tài)系統(tǒng)和令人驚嘆的社區(qū)勝過F#提供的任何靜態(tài)鍵入好處。
· Dark的新后端將在F#中
(13) 獲獎(jiǎng)情況
F#獲得了兩個(gè)獎(jiǎng)項(xiàng)。
F#獲得了Fintech最佳語言獎(jiǎng)。財(cái)務(wù)是F#的最大應(yīng)用之一,這已經(jīng)不是什么秘密了。
F#還獲得了企業(yè)軟件最佳語言獎(jiǎng)。其豐富的類型系統(tǒng)允許對(duì)復(fù)雜的業(yè)務(wù)邏輯進(jìn)行建模。強(qiáng)烈建議您閱讀《領(lǐng)域建模使功能》一書。
ReasonML
ReasonML是一種功能強(qiáng)大的js編譯語言,主要用于前端Web開發(fā)。
ReasonML不是一種新語言,它是OCaml(一種古老且嘗試過的編程語言)的新語法。ReasonML由Facebook支持。
通過利用JavaScript生態(tài)系統(tǒng),ReasonML不會(huì)遭受與OCaml相同的弊端。
語言家族:ML。
(1) 不是JavaScript的超集
ReasonML的語法與JavaScript相似,這使具有JavaScript經(jīng)驗(yàn)的任何人都可以更容易地使用它。但是,與TypeScript不同,ReasonML甚至沒有嘗試成為JavaScript的超集(這是我們已經(jīng)學(xué)到的一件好事)。與TypeScript不同,ReasonML不必繼承數(shù)十年來JavaScript做出的錯(cuò)誤設(shè)計(jì)決策。
(2) 學(xué)習(xí)曲線
由于ReasonML甚至沒有嘗試成為JavaScript的超集,因此它使該語言比JavaScript簡(jiǎn)單得多。具備JavaScript函數(shù)編程經(jīng)驗(yàn)的人可以在一周左右的時(shí)間內(nèi)使用ReasonML。
ReasonML確實(shí)是最簡(jiǎn)單的編程語言之一。
(3) 函數(shù)式,但不純粹
與Elm不同,ReasonML甚至沒有嘗試成為純函數(shù)式語言,也沒有"永遠(yuǎn)不會(huì)出現(xiàn)運(yùn)行錯(cuò)誤"的目標(biāo)。這意味著ReasonML非常實(shí)用,專注于開發(fā)人員的生產(chǎn)力,并快速實(shí)現(xiàn)結(jié)果。
(4) 類型系統(tǒng)
ReasonML實(shí)際上是OCaml,這意味著它的類型系統(tǒng)幾乎與Haskell一樣好。最大的缺點(diǎn)是缺少類型類,但它支持仿函數(shù)(高階模塊)。
ReasonML是靜態(tài)類型的,其類型推斷幾乎與Haskell一樣好。
(5) 生態(tài)
就像TypeScript一樣,ReasonML可以訪問整個(gè)JavaScript生態(tài)系統(tǒng)。
(6) JavaScript / TypeScript互操作
ReasonML編譯為純JavaScript。因此,可以在同一項(xiàng)目中同時(shí)使用ReasonML和JavaScript / TypeScript。
(7) ReasonML和React –天生一對(duì)
如果您正在進(jìn)行前端Web開發(fā),那么您很可能正在使用React。您知道嗎,React最初是用OCaml編寫的,然后才移植到JavaScript以幫助采用?
由于ReasonML是靜態(tài)類型的,因此無需擔(dān)心PropTypes。
還記得JavaScript一節(jié)中看起來很天真的示例,它可能導(dǎo)致性能下降嗎?
ReasonML對(duì)不可變數(shù)據(jù)結(jié)構(gòu)提供了適當(dāng)?shù)闹С?,并且此類代碼不會(huì)產(chǎn)生性能問題:
與JavaScript不同,ReasonML無需重新渲染任何內(nèi)容,即開即用的出色React性能!
(8) 工具
ReasonML尚未像TypeScript這樣的替代品那么成熟,并且該工具可能存在一些問題。例如,官方建議的VSCode擴(kuò)展原因語言服務(wù)器當(dāng)前已損壞,但是存在其他替代方法。
ReasonML在后臺(tái)使用OCaml編譯器,而OCaml則以非常糟糕的編譯器錯(cuò)誤消息而聞名。雖然不是交易破壞者,但這有點(diǎn)令人沮喪,并且會(huì)影響開發(fā)人員的生產(chǎn)率。
我希望隨著語言的成熟,工具也會(huì)有所改進(jìn)。
(9) 空值
ReasonML沒有空引用,并且使用Option模式來表示可能不存在的值。
(10) 不變性
ReasonML對(duì)不可變數(shù)據(jù)結(jié)構(gòu)具有一流的支持。
(11) 模式匹配
ReasonML具有強(qiáng)大的模式匹配支持。
(12) 結(jié)論 4.5星
ReasonML可能是TypeScript一直以來的目標(biāo),但是失敗了。ReasonML將靜態(tài)類型添加到JavaScript,同時(shí)刪除所有不良功能(并添加真正重要的現(xiàn)代功能)。
(13) 最佳前端語言獎(jiǎng)
最佳前端語言獎(jiǎng)歸于ReasonML。毫無疑問,ReasonML是前端Web開發(fā)的最佳選擇。
Elixir
Elixir可能是世界上最受歡迎的函數(shù)式編程語言。就像ReasonML一樣,Elixir并不是真正的新語言。取而代之的是,Elixir建立在Erlang超過三十年的成功基礎(chǔ)上。
Elixir是Go的函數(shù)表親。與Go一樣,Elixir也是從頭開始設(shè)計(jì)的,用于并發(fā)以利用多個(gè)處理器內(nèi)核。
與其他一些功能語言不同,Elixir非常實(shí)用。它專注于獲得結(jié)果。在Elixir社區(qū)中,您不會(huì)找到長(zhǎng)時(shí)間的學(xué)術(shù)討論。Elixir論壇上充滿了針對(duì)實(shí)際現(xiàn)實(shí)問題的解決方案,社區(qū)對(duì)初學(xué)者非常友好。
語言家族:ML。
(1) 生態(tài)
真正使Elixir發(fā)光的是其生態(tài)系統(tǒng)。在大多數(shù)其他語言中,有兩種語言,然后是生態(tài)系統(tǒng),這是兩個(gè)獨(dú)立的部分。在Elixir中,核心Elixir團(tuán)隊(duì)正在開發(fā)生態(tài)系統(tǒng)中的核心框架。Elixir的創(chuàng)建者JoséValim還是Phoenix和Ecto(Elixir生態(tài)系統(tǒng)中的超酷庫)的主要貢獻(xiàn)者。
在大多數(shù)其他語言中,有多個(gè)不同的庫專注于同一任務(wù)-許多不同的Web服務(wù)器,許多不同的ORM等。在Elixir中,開發(fā)工作實(shí)際上集中在少數(shù)幾個(gè)核心庫上,這導(dǎo)致了出色的庫質(zhì)量。
Elixir庫的文檔非常好,有很多示例。與某些其他語言不同,標(biāo)準(zhǔn)庫的文檔也很好。
(2) Phoenix框架
Phoenix框架的口號(hào)是" Phoenix感覺不錯(cuò)"。與其他語言的框架不同,Phoenix具有許多內(nèi)置功能。開箱即用,它支持WebSocket,路由,HTML模板語言,國(guó)際化,JSON編碼器/解碼器,無縫ORM集成(Ecto),會(huì)話,SPA工具包等。
Phoenix框架以其出色的性能而聞名,它能夠在一臺(tái)計(jì)算機(jī)上處理數(shù)百萬個(gè)同時(shí)連接。
(3) 全棧
Phoenix框架最近引入了LiveView,它允許在Elixir(認(rèn)為單頁應(yīng)用程序)內(nèi)構(gòu)建豐富的實(shí)時(shí)Web界面。無需JavaScript,無需React!
LiveView甚至負(fù)責(zé)同步客戶端和服務(wù)器狀態(tài),這意味著我們不必?fù)?dān)心開發(fā)和維護(hù)REST / GraphQL API。
(4) 數(shù)據(jù)處理
對(duì)于許多與數(shù)據(jù)處理有關(guān)的任務(wù),Elixir可以替代Python。在Python和Elixir中都構(gòu)建了一個(gè)Web抓取工具之后,Elixir無疑是完成任務(wù)的更好的語言和生態(tài)系統(tǒng)。
諸如Broadway之類的工具允許在Elixir中構(gòu)建數(shù)據(jù)提取/數(shù)據(jù)處理管道。
(5) 類型系統(tǒng)
我認(rèn)為,缺少適當(dāng)?shù)撵o態(tài)類型是Elixir的最大缺點(diǎn)。雖然Elixir不是靜態(tài)類型的,但編譯器(以及透析器)將在編譯時(shí)報(bào)告很多錯(cuò)誤。與動(dòng)態(tài)類型的語言(例如JavaScript,Python和Clojure)相比,這有很長(zhǎng)的路要走。
(6) 速度
Elixir編譯器是多線程的,可提供極快的編譯速度。與Java虛擬機(jī)不同,Erlang VM快速啟動(dòng)。對(duì)于Elixir的用例,運(yùn)行時(shí)性能非常好。
(7) 可靠性
Elixir建立在Erlang之上,Erlang被使用了30多年來構(gòu)建世界上最可靠的軟件。在Erlang VM上運(yùn)行的某些程序已經(jīng)能夠?qū)崿F(xiàn)99.9999999%的可靠性。世界上沒有其他平臺(tái)可以擁有同等水平的可靠性。
(8) 并發(fā)
大多數(shù)其他編程語言尚未設(shè)計(jì)用于并發(fā)。這意味著編寫使用多個(gè)線程/處理器內(nèi)核的代碼絕非易事。其他編程語言使用執(zhí)行并行代碼(和共享內(nèi)存,線程從中讀取/寫入)的線程。這種方法通常容易出錯(cuò),容易出現(xiàn)死鎖,并導(dǎo)致復(fù)雜度成指數(shù)增長(zhǎng)。
Elixir建立在以其出色的并發(fā)功能而聞名的Erlang之上,并采用了一種完全不同的并發(fā)方法,稱為actor模型。在此模型中,流程(參與者)之間沒有任何共享。每個(gè)進(jìn)程都維護(hù)自己的內(nèi)部狀態(tài),并且各個(gè)進(jìn)程之間進(jìn)行通信的唯一方法是發(fā)送消息。
順便說一下,參與者模型實(shí)際上是其創(chuàng)建者Alan Kay最初打算使用的OOP,其中沒有任何共享,對(duì)象僅通過傳遞消息進(jìn)行通信。
讓我們快速比較一下Elixir和它的命令表親Go。與Go不同,Elixir完全是為容錯(cuò)而設(shè)計(jì)的。每當(dāng)goroutine崩潰時(shí),整個(gè)Go程序都會(huì)關(guān)閉。在Elixir中,每當(dāng)一個(gè)進(jìn)程死亡時(shí),只有那個(gè)單個(gè)進(jìn)程死亡,而不會(huì)影響程序的其余部分。更好的是,失敗的進(jìn)程將由其主管自動(dòng)重啟。這允許失敗的進(jìn)程重試失敗的操作。
Elixir的流程也非常輕巧,可以在一臺(tái)機(jī)器上輕松運(yùn)行數(shù)十萬個(gè)流程。
(9) 縮放
讓我們?cè)倥cGo進(jìn)行比較。Go和Elixir中的并發(fā)利用并發(fā)進(jìn)程之間的消息傳遞。由于Go可以編譯為本地代碼,因此Go程序?qū)⒃诘谝慌_(tái)計(jì)算機(jī)上運(yùn)行得更快。
但是,一旦您開始擴(kuò)展到第一臺(tái)機(jī)器之外,Go程序就會(huì)開始丟失。為什么?因?yàn)镋lixir是從頭開始設(shè)計(jì)的,因此可以在多臺(tái)機(jī)器上運(yùn)行。當(dāng)涉及到分發(fā)和擴(kuò)展時(shí),Elixir在其之上運(yùn)行的Erlang VM確實(shí)令人眼前一亮。它無縫地處理了許多繁瑣的事情,例如集群,RPC功能和網(wǎng)絡(luò)。
從某種意義上說,Erlang VM在微服務(wù)成為現(xiàn)實(shí)之前就已經(jīng)在進(jìn)行微服務(wù)了。每個(gè)進(jìn)程都可以視為微服務(wù)-就像微服務(wù)一樣,進(jìn)程彼此獨(dú)立。通過語言內(nèi)置的通信機(jī)制,進(jìn)程可以跨多臺(tái)機(jī)器運(yùn)行的情況并不少見。
沒有Kubernetes復(fù)雜性的微服務(wù)?檢查一下這就是Elixir真正設(shè)計(jì)的目的。
(10) 錯(cuò)誤處理
Elixir采用非常獨(dú)特的方法來處理錯(cuò)誤。盡管純函數(shù)式語言(Haskell / Elm)旨在最大程度地減少錯(cuò)誤發(fā)生的可能性,但Elixir認(rèn)為錯(cuò)誤不可避免地會(huì)發(fā)生。
在Elixir中,拋出異常很好,而通常不建議捕獲異常。相反,流程主管將自動(dòng)重新啟動(dòng)失敗的流程,以保持程序運(yùn)行。
(11) 學(xué)習(xí)曲線
Elixir是一種簡(jiǎn)單的語言,人們可以在大約一兩個(gè)月后拿起Elixir。使學(xué)習(xí)變得有些困難的是OTP。
OTP是Elixir的"殺手feature"。OTP是Elixir構(gòu)建的Erlang的一組工具和庫。正是"秘密調(diào)味料"極大地簡(jiǎn)化了構(gòu)建并發(fā)和分布式程序的過程。
盡管Elixir本身很簡(jiǎn)單,但將頭纏在OTP上可能要花費(fèi)一些時(shí)間,但這確實(shí)對(duì)我有用。
(12) 學(xué)習(xí)資源
作為最受歡迎的函數(shù)式編程語言,Elixir具有豐富的學(xué)習(xí)資源。關(guān)于實(shí)用程序程序員,有許多驚人的Elixir書。學(xué)習(xí)資源幾乎總是對(duì)初學(xué)者非常友好。
(13) 模式匹配
Elixir具有出色的模式匹配支持。
(14) numbers運(yùn)算數(shù)字
Elixir無法很好地處理計(jì)算密集型任務(wù)。對(duì)于此類任務(wù),應(yīng)選擇本機(jī)編譯語言(Go / Rust是不錯(cuò)的選擇)。
(15) 好吧,和Erlang有什么關(guān)系?
出于所有意圖和目的,Elixir和Erlang完全相同。Erlang是一種功能強(qiáng)大的語言,具有奇怪的語法。Elixir可以被認(rèn)為是Erlang的一種更好,更現(xiàn)代的語法(以及非常好的生態(tài)系統(tǒng)和社區(qū))。
(16) 結(jié)論 4.5星
Elixir可能是所有函數(shù)式語言中最成熟的。它還在用于功能編程的虛擬機(jī)之上運(yùn)行。它是專為并發(fā)而設(shè)計(jì)的,非常適合現(xiàn)代多核處理器時(shí)代。
(17) 獲獎(jiǎng)情況
Elixir獲得兩個(gè)獎(jiǎng)項(xiàng)。
它的彈性,函數(shù)至上的方法和令人驚嘆的生態(tài)系統(tǒng)使其成為構(gòu)建Web API的最佳語言。
OTP和參與者模型使Elixir成為構(gòu)建并發(fā)和分布式軟件的最佳語言。與命令式表弟Go不同,用Elixir編寫的軟件可以水平擴(kuò)展到數(shù)千臺(tái)服務(wù)器,并且具有開箱即用的容錯(cuò)能力。
為什么不使用正確的工具進(jìn)行工作?
> Photo by Haupes Co. on Unsplash
你會(huì)用螺絲刀打釘嗎?可能不會(huì)。然后,我們可能不應(yīng)該嘗試對(duì)所有內(nèi)容都使用一種編程語言,每種語言都有自己的位置。
Go是用于系統(tǒng)編程的最佳語言。前端開發(fā)的最佳選擇無疑是ReasonML,它滿足了出色編程語言的大多數(shù)要求。Web API開發(fā)的絕對(duì)贏家是Elixir,它的唯一缺點(diǎn)是缺少靜態(tài)類型系統(tǒng)(它被強(qiáng)大的生態(tài)系統(tǒng),社區(qū),可靠性和并發(fā)功能所抵消)。對(duì)于任何種類的并發(fā)/分布式軟件,最好的選擇還是Elixir。
如果你正在從事數(shù)據(jù)科學(xué)工作,那么不幸的是,唯一合理的選擇是Python。
我真的希望這篇文章有用。比較編程語言絕非易事,但我已盡力而為。