Lisp 和 Haskell 各有什麼優缺點?學哪個好?


Haskell獨樹一格, 較值得學習, 因為就算有語言仿造移植Haskell特性, 例如Java也有Monad函式庫, 也幾乎沒啥人會花心思去用, 非得學過Haskell被迫使用純函數式後, 那些概念才能用得起來, 才能體會其好處

Lisp比較不需要特別去學, javascript以前跟Lisp一樣標榜自由, 但由於各種混亂javascript代碼的出現, 而使得javascript越趨嚴格, Lisp則沒有任何嚴格化的機會, Macro語法各自為政的機會很大, 很難在社群中通用起來, 小組應用比較有可能, Clojure有改善這點, 讓寫法比較容易趨於一致


Reddit Lisp社區:Haskellers of Lisp: What is Your Experience Using Haskell? : lisp

Reddit Haskell社區:Lispers of Haskell: Whats Your Experience Using Haskell versus a Lisp? (x-post on /r/lisp) : haskell


這兩門語言從不同的角度去解決了一個共同的問題:如何減少重複代碼,如何提高抽象

首先兩門語言都是建立在lamdba演算之上,都提供了first class的函數支持,所以在這兩門語言里函數都是構建計算的基本單元,而不是c系語言的statement。

但是即使是書寫函數,人們依然希望獲得更加高級的抽象,來減少重複,舉幾個具體的例子:

  • 解析文本這個過程,前進buffer &>&> 判斷是否符合當前的語法結構 &>&> 失敗了?報錯 &>&> 成功了繼續重複(重複的代碼:判斷)

  • 渲染模版的過程,計算一個模版片段 &>&> 計算下一個模版片段 &>&> 把模版片段相連 &>&> 繼續重複 (重複的代碼:相連)

  • 設計一個狀態機的過程,拿到上一個計算之後的狀態值 &>&> 基於這個值運行狀態機,產生新的狀態和可能的計算結果 &>&> 繼續重複 (重複的過程:狀態傳遞)

我們看到這個時候依賴人工書寫這些代碼會出現大量重複的情況,LISP的思路基於語法結構,LISP巧妙的利用lamdba的基本書寫形式 (lamapp variables),構建了模版(marco),這意味著只要是一段代碼具有相同的語法結構,比如重複地進行判斷,你都可以把它抽象為模版,由編譯器或者解釋器來替你做語法層面的替換,自動生產重複的代碼。需要注意的是LISP的模版抽象是基於語法樹(AST)而不是字元串的,同時LISP的AST非常簡單,這意味著書寫構建AST的模版也非常簡單。

Haskell的思路是建立在類型類多態的基礎上的,haskell里構建大規模計算的類型類是Monad,它定義了一個多態的連接函數bind,aka. &>&>= 。 這個函數的作用是連接上下兩段相同類型的運算。在這個連接的過程中,你可以通過定義判斷,或者相連,或者傳遞狀態等等,來實現不同的計算語義,這個類型類是haskell減少代碼重複的關鍵。而這個構建計算的框架和haskell的強類型系統非常契合

當然LISP也可以實現一個untyped的monad模版,haskell也支持template haskell,所以在LISP里monad這是眾多模版中的一個,而在Haskell中,LISP的AST也只是眾多語法結構里比較底層的一個。但是這些並不意味著誰比誰更加強大,這只是兩個語言解決問題的思路不同

所以無論如何,如果可以,請把這兩門語言都認真的學習一番,即使你可能不在實踐中使用它們,它們都會給你帶去很不一樣的編程思路。


學習Haskell中。對排名第一的答案表示疑惑。

社區里是會有很多人在那裡發表一些玩Haskell的帖子,但不表示Haskell只是一個玩具語言。把Ruby和Python當玩具的人也不少吧。

國外公司用Haskell也不少了,Reddit上時不時的有招聘帖。Yesod,Faylang,Haste, Elm這些都可以用在Web開發中,NetWire可以用在遊戲開發中。而且現在也可以通過GHC開發iOS和Android應用了。

還有PureScript(包括Faylang, Haste),可以用Haskell的語法寫JavaScript,可以用在所有可以運行JavaScript的地方。即使不用PureScript寫JS代碼,也可以用它的QuickCheck寫JS的測試。

PS: 想體驗一下用函數式語言寫JS的爽感的,可以體驗一下Elm的在線編輯,有木有XCode里調試Swift的感覺 http://debug.elm-lang.org/edit/Mario.elm

我對Lisp不是很了解。喜歡Lisp可以了解Clojure或者Shen,他們寄托在Java,以及Python這類應用很廣泛的語言之上,工作中想用肯定是沒問題的。

PS:有一個匿名用戶貼了一個Quora的鏈接,

Over the years, these features started migrating into other languages, and Lisp no longer had a unique position; today, the macro system is the only remaining feature in which Lisp excels compared to other languages.

現在用Lisp做AI不多了,那都是幾十年前的事情。


謝謝邀請。

程序世界裡,選擇了一門語言,實際上也同時選擇了很多東西:一種思維方式,一個平台,一個社區,往往還限定了一個工程領域。所以,選擇一門語言沒有那麼簡單。

思維方式而言,兩者相差並不多。考慮到函數式編程並不是如今程序開發的主流,無論是 Lisp 還是 Haskell,它們和主流工程實踐都相差很多。但具體到函數式程序設計語言之間,基本的思路是類似的。函數式程序設計的風格的實質:去除賦值的副作用,自包含上下文的高階函數,以「值」的流動而不是操作的變化為中心設計程序,這在兩門語言中都是一樣的。當然,在細節上兩門語言仍然有區別:Lisp 的宏展開,弱類型/動態類型,Haskell 的惰性求值,強類型,都有各自的區別。具體開始使用時,需要注意其特性才能用好。

在社區上,Lisp 有固定的社區,但由於大量 Lisp 方言的存在,導致如今的分裂得很厲害。除了 Common Lisp 這個大型社區外,還有各種小型 Lisp 社區,星羅棋布。這使得 Lisp 社區事實上很難形成合力做出一個各個方言通用的平台——是的,即使 Common Lisp 是最大的社區,從源流上看,它也依然是方言之一。我必須承認,這一點上 Haskell 要好得太多。Haskell 的社區通過 http://www.haskell.org 很好地被統一在一起,無論是教學還是開發,都容易集合整個社區的力量。

談到工程領域,至少目前為止,Haskell 社區在宣傳時一直是將其定位為一門通用程序設計語言的。但恕我直言,現在這個社區還沒有找到真正適合自己的工作場景,或者說,這個社區的成熟程度還不足以支撐一個適合自己的工作場景。在我的眼裡,這個社區的核心,仍然是一門玩具語言。反觀 Lisp 社區,他們的應用場景簡單而專註:符號推演和人工智慧;與此同時,許多 Lisp 方言也將自己的觸角伸進實際工程領域,配合其他語言使用。也有 Emacs 和 Gimp 這樣各自領域內公認的通用軟體。

註:不要誤會,我對 Haskell 語言本身沒有惡感。作為工具,語言無所謂好壞。但是,作為嚴肅的工程人員,我們應該理解這樣一條基本原理:語言作為工具,它必須也只能立足於解決問題。但是 Haskell 這個社區顯然不理解這樣一條原則。這個社區一開始熱捧的惰性求值,以及後來的 Monad,再到最近似乎又被拉出來宣傳的所謂類型自動推演,無一不是這門語言本身的特性。而對比其他社區,我們不難看到,這個社區至今也沒有生產出哪一個可以使用的,可以解決通用工程問題的軟體。我知道 Haskell 愛好者會出來反對,但我仍然堅持認為:僅僅是滿足於在各個公司里做一些邊角的小工具,是不足以證明其作為通用程序設計語言的價值的。而即使是這個社區熱捧的語言特性,在編譯器理論中,事實上都不是新鮮事物。作 Haskell 社區曾經的一員,我很難想像一個社區會如此十幾年如一日地陶醉在自己的語言特性中不能自拔。不過,公允地說,Lisp 社區中的一部分人中也存在這種惡劣的傾向;但是 Lisp 社區中專註於工程實踐的力量能在相當程度上平衡這種缺陷,讓社區保持清醒。

所以結論:Lisp 可以作為學習時的主力語言,和工業開發時的輔助語言。如果提問者的專業是符號推演或人工智慧,Lisp 可以說是必須學的語言。至於 Haskell,我仍然要重複我在無數場合說了無數次的結論:有空可以玩玩 Haskell,但不要認為它是能夠勝任工程實踐的工具;儘可能避免接觸 Haskell 這個社區,那不是一個健康的社區。

順便說一句,如果確實希望學習類型系統和強類型環境下的函數式程序設計風格,我更推薦 OCaml。這門語言的特性也許沒有 Haskell 那麼多,但其社區要健康許多。


都學了唄,不學說了你也不懂,學了自然就知道了。


簡述一下兩種語言:

無須多言,Lisp和Haskell都是函數式語言。但在函數式這一點上,兩者都有純粹和不純粹的地方,這一點見仁見智。

----------

Lisp是古老的函數語言,弱類型,動態推斷。這使得Lisp中最基本的數據結構——List——有很多漂亮的特性:

1. 它的每一個表項中可以儲存任何類型的數據:數字、符號、函數或者一個子表;在書寫程序時,表可以隨意擴展、被操作;

2. Lisp代碼本身就是一個個表。這使得用Lisp語言構造一個自己的解釋器變得非常簡單、有趣。

弱類型這個優點帶來的缺點則是運行效率的低下。當然,這與現代計算機的體系結構也有關係;王垠和他的老師並不同意這一觀點,他們對Chez Scheme及其免費版Petite推崇備至:(chez (chez scheme)),野心勃勃的王垠菌還曾設想從體系結構開始建造函數式計算機(blog已刪,出處欠奉)。總之,就這一點而言,Lisp是自由而純粹的。

----------

最古老、核心的Lisp只有7個操作符:quote, atom, eq, car, cdr, cons, cond (wiki: LISP) 其中,前三者用於符號的推斷;car ... cons操縱表格;cond負責分支判斷。從定義來看,最古老的Lisp是非常非常貼近圖靈機原始定義的純函數式語言,其簡潔是現代語言完全無法比擬的。

簡潔的缺點是複雜,它讓開發大的工程變得比較困難:從二維表查詢到面向對象,從底層到高層,需要嵌套許多的函數來實現。為了改善這一點,Lisp衍生出了許多方言:Common Lisp是最先成為主流的語言,它逐漸偏向了面向對象的發展路線。這使得Lisp原教旨主義者非常憤慨,他們另行維護了Scheme這一分支,用以保證Lisp的簡潔和純粹性。後來,Scheme分支又衍生出了新的分支,包括mit-scheme這一比較純粹的分支,以及Racket這一野心勃勃、功能完備然而效率低下的分支。

但是,上述的Lisp都引入了一個可怕賦值的符號:set! 。函數式語言的特性保證了兩次調用同一個函數必定返回同一個值;這個符號打破了函數式語言不可賦值的清規戒律,使得時間重新成為編程中不可忽略的可怕的因素——賦值的前後關係、函數調用順序、並發的執行順序都可能影響程序的結果。就這一點而言,Lisp是不純粹的。

--------------------

Haskell編程經驗不多,大體是概述,不敢多說,甚至可能有錯。

受ML語言影響,Haskell是現代的函數語言,它是強類型的,包含了強有力的靜態類型推斷。強類型帶來效率上的大大提升,也阻止了大量錯誤的發生。然而與Lisp相比,降低了自由性。你不再能優雅地用一個表展開自己、完成所有的操作了。

Haskell(宣稱)是純粹的函數式語言,沒有副作用。即使在I/O這個高度上,他們也有自己引以為傲的I/O Monad。很容易想像,I/O是順序操作,具有強烈的反函數式的傾向。Haskell則給了他一個很好的封裝,使得在使用時可以不去顧忌副作用,從這個角度而言,它是純粹的。不過,StackOverflow上有評論說道(出處欠奉),凡是涉及到I/O時,都可以用某種黑魔法破壞函數式語言的純粹性。從程序員的角度而言,這是可以設法避免的。

--------------------

現在,Haskell,以及與其同族的Erlang等語言,擁有許多的應用場景,來用純粹函數式的特性解決高並發的互聯網請求。Whatsapp就是其中一個例子;

而相對的,Lisp仍然更少介入實際應用。但是,Ruby / JavaScript等語言受其影響深刻。尤其是Ruby,其複製賦值用setvalue、原地賦值用setvalue!,詢問用query? 謂詞風格完全傳承了Lisp;而在了解了Lisp風格的函數閉包以後,也更容易理解JavaScript里常用的技巧。


Haskell vs OCaml Functional Programming: Which of Haskell and OCaml is more practical?

Lisp for AI? Is it true that Lisp is highly used programming language in AI?

Just FYI.


Haskhell這種純函數式,外人看著像是自虐,習慣的人會覺得自虐得很爽。

Lisp 也是。

別的語言都是這樣。比如Java也是自虐。

的確Iisp已經沒啥特色可以學的,都被別的語言借鑒走了,但是用來快速原型開發是沒得說的。

兩者的共同特點是基本沒什麼好的庫,因為精通以後隨手就寫一個順手的出來。

然後如果能成功寫出來個上萬行的項目然後賣掉,那麼恭喜你,以後不會失業了,因為只有你自己能看懂,維護只能找你來。


這個問題更廣義地說是untyped functional programming和typed functional programming的比較。我更喜歡後者,因為類型提供的編譯期安全檢查非常有價值。前者最大的優點(後者很難實現)是程序對自身abstract syntax tree進行操作這個能力(reflection或reification),也就是常說的「超強macro編程能力」,但我仍然對這種能力的實際價值持懷疑態度。

Haskell的一些特點是自身特有的,並不能代表所有typed functional programming。比如laziness和purity,我對這兩者的實際價值也持懷疑態度。它們導致了Haskell在學習和使用上的不必要的複雜。我覺得Standard ML是對typed functional programming更好的代表,而且在優雅和實用性間找到了最好的平衡。

OCaml可以被認為是Standard ML的一個方言,兩者的比較可以參見:Comparing Objective Caml and Standard ML

比較結果是OCaml更偏重使用方便,Standard ML更偏重理論嚴謹和優雅(我個人體會是使用也很方便!)。這兩者的選擇就看個人口味了。


作為平庸的程序員,感覺兩個語言對我來說都沒什麼用,還是Java更有用。

如果非要強行有用的話,

Haskell讓我了解到了類型系統的重要性。

Lisp讓我能更好地配置emacs。當然,作為Java程序員,emacs對我也沒用。

所以,還是學haskell比較好。


lisp 不是純函數式,是多範式的語言。不要學lisp,你也學不到什麼東西,還不如學 js。放到幾十年前,lisp的優勢是提供了許多獨佔特性,比如 gc和分支結構,現在都被其它語言瓜分完了。二者選一的話,還是選haskell。

此外,純函數式語言學學就好,不要用它來指導實踐。實際作用 oo + fp &> 純oo &> 純fp。


推薦閱讀:

C# 兩種遍歷列表的方式,哪種更高效?
為什麼數據分析需要會編程語言?
為什麼很多語言中,要用三個引號或其他符號來表示多行字元串字面量?
關於 Type Inference 的各種應用和學習資料?
三宮六院七十二妃(程序YUAN版)

TAG:編程語言 | 函數式編程 | Haskell | Lisp |