標籤:

編譯原理學了有什麼用?

想知道一些編譯原理這門課程的實際應用,感覺這課很枯燥啊


對於普通程序員,我認為編譯原理這門課主要掌握幾點就夠用了:

1. 詞法分析方面,掌握正則表達式,了解dfa/nfa。

2. Parsing 方面,能讀懂BNF,知道AST,會寫簡單的遞歸下降parser,會用antlr之類的parser generator。

3. 優化方面,知道現代編譯器的優化能力有多強,知道如何配合編譯器寫出高效易讀的代碼,避免試圖outsmart編譯器。

4. 會實現簡單的虛擬機(stack-based,不帶GC),並把四則運算表達式翻譯為虛擬機指令。


你現在覺得枯燥,我想既跟編譯原理本身比較抽象的知識有關,也跟講述者有關。一個好的講述者會試著化抽象為形象,以豐富生動的例子來為你解釋。而編譯原理是否有用?我認為這門課是一門真正與代碼做鬥爭的課程,對於一個有至於追求技術的人是不容錯過的課程,而且編譯原理可以說是一個計算機科學的縮影。你學習它更多的是去追尋程序設計語言的本質,如它在寄存器分配中將會使用到貪心演算法,死代碼消除中將會使用到圖論演算法,數據流分析中使用到的Fixed-Point Algorithm,詞法分析與語法分析中使用到有限狀態機與遞歸下降這樣的重要思想等等,也許你以後不會成為一個編譯器開發工作者,但是編譯原理的學習中所獲,所思的東西足以讓你終生獲益。同時,學完這門課程,對於一個有Geek精神的開發者,他會開始運用自己的所學開發享受「上帝」的感覺,去嘗試創造一門語言,我想這種感覺不是每門課程都能帶給你的。我相信,當你真正完成這個過程後,你對你所寫的程序、程序語言都會有更深的本質認識,這樣的認識也會讓你站的高度完全不同,如果你真的學的好,我想別人看到的是語法,你看到的是背後的實現,這樣的感覺真的很好的,不信你試試。有了這麼多好處,無論如何都有足夠的理由支撐你好好學習了。


關於編譯原理我一直最喜歡類比的就是人體解剖 。

在歐洲教會還不允許做屍體解剖的時候就有兩類人在一起偷偷摸摸的搞人體解剖:一類是醫生,從外科手術的角度來說應該比較容易理解,不解剖根本不可能知道如何做外科手術;還一類則是畫家,他們只是為了可以更好的在描繪皮膚時體現肌肉的質感,就願意冒著被教會處罰的危險來參與人體解剖。而且即使是現在,所有的現代繪畫的教育雖然不會再像醫生那樣實際操作解剖,但是肌肉層的解剖圖仍然是必修課。

在我看來,完全不懂編譯原理的程序員,就好像是完全沒有學過人體解剖圖的畫家一樣,當然不會說一定就無法成功,不過如果有更好的基礎可以提高成功的幾率。在知道底層的情況下,對上層的描繪會更加寫實,更加生動。

拋開比喻,從現實的方面來說,編譯原理學過之後的益處(不考慮最後都沒有入門的情況)包括:

1、可以更加容易的理解在一個語言種哪些寫法是等價的,哪些是有差異的

2、可以更加客觀的比較不同語言的差異

3、更不容易被某個特定語言的宣揚者忽悠

4、學習新的語言是效率也會更高

5、其實從語言a轉換到語言b是一個通用的需求,學好編譯原理處理此類需求時會更加遊刃有餘

另外還有一點,就是一直有人說不用重複造輪子,所以不需要學習編譯原理這樣的課程。我想說的是,學編譯原理不是讓你去造輪子(大多數人的實力,學了也造不出輪子),而是要讓你知道現在一共有多少種輪子可以選擇,它們特性如何?

就比如f1比賽,其實現在所有的車隊可選的輪胎都是一樣的,但不同車隊根據自己車的情況和戰術等做出的選擇就會截然不同。如果你對輪胎的理解只是它可以轉,那麼你根本無法把它的能力發揮到極限。


自從學會了編譯原理,我用編譯原理的眼光來看帶我自己的代碼,寫出了優秀的單元測試。


裝逼利器,必學必備。


說點編譯相關知識在前端或其他方面的應用:

- 寫了一個解析 html 轉換成其他組件的工具,詳見 https://zhuanlan.zhihu.com/p/28798319 這篇文章

- babel 是一個非常有趣的 js compiler,基於 es-ast 的編譯器還有很多,如 jscodeshift 依賴的 recast 等。理解了代碼被 tokenizer 解析到 ast 再到 output 才能更好的應用,比如實現代碼重構、特殊編譯等。

- 模版引擎,解析這樣的 {{ content }},還有這樣的 {% for i in [0..10] %} 語句肯定是需要有parse的過程。如果你有興趣,可以看看vue的實現 vuejs/vue - JavaScript

- parse 常用的數據通訊格式格式如解析 json/proto。在早期一些老瀏覽器不支持JSON內置對象的時候,JSON的parse和stringify用的第三方庫 douglascrockford/JSON-js: JSON in JavaScript

- 以及 GraphQL 的實現,你可以理解他就是用一個請求的scheme來減少創建格式各樣api的形式,對於整個scheme的處理,當然也要parser graphql-js/parser.js at master · graphql/graphql-js · GitHub

- Node.JS 的引擎:v8、Chakra,我想他們改進的不僅僅是 JavaScript 的執行速度和語法吧

不知道舉得幾個栗子符不符合題主胃口..我之前也認為學習編譯原理可能真的要寫一個能把一個xx語言 parse 完 execute 成功才算ok,那個才叫編譯器神馬的...也是接觸到這些東西之後開啟了新世界的大門,原來「編譯」這個概念應用如此之廣


--------《C編譯器剖析》序又想起了《編譯原理》的封面:

意思很明顯,編譯原理就是計算機科學裡面的屠龍術啊!


一個實際應用例子:

有個程序本來在代碼中寫死了公式,這樣要加新功能就需要每次就要改代碼重新編譯。

後來把公式以文本方式放到config中,但是公式中涉及到算術計算和函數調用、參數等。這時候最簡單的方法就是藉助一些工具比如anltr,自己寫一個不涉及完整語言的函數定義、包管理等,簡單的單行DSL了。

PS:題主求實際應用,怎麼滿屏都是怎麼學、學什麼、學不好、學了也沒用。。。


學完了編譯原理,你就可以跟別人到GitHub上約架比賽寫tokenizer和parser啦。


如果是本科學完基礎課程之後,學校開的一門名字叫《編譯原理》的課,那基本上沒「實際應用」。

這門課通常開一個學期,每個學期20星期,每個星期兩節課,總共也才40節課,40節還不是滿的,通常情況下中間還有放假、還有上個學期或本學期的課程設計和其它內容,又要扣除部分課時,算30節。30節以國內慣有的照本宣科的教學方法,基本上講不了什麼內容,所以通常情況下只能集中擺弄詞法分析和語法分析的各種經典理論和方法,狀態機、什麼LL、LR之類的,拿著一堆莫名其妙的符號在黑板上擺弄,填表。這麼點知識有什麼用?《編譯原理》課程設計就能看出來了,可以針對課堂上學過的語法分析方法寫一種叫「語法分析器生成器」的東西,這種東西可以做點計算器什麼的、或者分析一些有簡單模式的文本。沒有非常吸引人的結果(語法分析器生成器還不如http://ASP.NET做個網頁有用)、也沒有有效的教學過程(反覆擺弄一堆符號),課程必定枯燥,不想學是應該的。

我有個老師有意思,說「上我的課就要學會寫編譯器」,能運行的那種。他把編譯器解釋成「把一個裝著程序的字元串切成詞,把片語裝成樹,然後把樹弄成線性的」這麼個過程,可以說通常情況下,編譯器就是這麼個過程。如果用上《編譯原理》課程差不多的時間,跳過市面上流行的一些反覆擺弄大量符號附送證明過程的寫得很爛的書(有的名氣還非常大,甚至等同於「編譯原理」書籍中的《C程序設計》)去了解一下目前編譯器構造的最流行的、直接的方法,然後動手寫實踐,足夠寫一個小型的編程語言了,高級語言執行的過程經過親手實踐在腦子裡就比以前更清晰了一步。這時候「實際應用」就多了不少,可以擴展到給自己寫的其它程序增加腳本語言、可以給現有語言實現進行更加深度的擴展等等。當然了,這點「實際應用」和其它課程一樣,大部分時候也用不著,沒啥意義。


可以寫一個像我這樣的編譯器

https://github.com/xiang1993/jack-compiler


我沒有具體學過編譯原理,但是我暑假實習寫iOS的時候,有種強烈的願望,就是去把編譯原理學一遍,那樣能省我不少事


沒學之前,人前,總是認為自己是工人。

學了之後,人前,我他么是工程師你知不知道。


計算器就是用到編譯原理的知識,如果自己寫一個是不是很好玩?

文本編輯器的代碼高亮功能,代碼提示功能就是運用編譯原理知識,如果自己寫一個是不是很好玩?

聊天機器人就是用的編譯原理的知識,如果自己寫一個是不是很好玩?


專家級程序猿大概三五年用到一次。

你覺得很枯燥,是因為教材上重點講理論,如果從某個parser generator的helloworld開始講, 其實是很直觀的。

可惜我朝寫編程教課書的人一般不會寫程序, 你讓他們去學個bison/flex啥的,簡直比你現在學編譯痛苦十倍不止,真正是要了他們的老命了, 所以上面覺得,還是讓你枯燥一點吧:)


就是當上班了,老闆突然說,「我們來自己造個輪子,設計個語言,方便別人做實驗」(題主感興趣可以挑些能寫的展開寫寫),然後指著我說,「小伙,你閑,不如你去干吧」。這個時候,我可以有那麼一點點底氣,默默坐下來開始寫解釋器。

拿c++寫的,全職寫了大概一個半月(花在解釋器上的時間估計3周左右,畢竟還有些其他work要做),勉強寫了個類似python語法的小語言來當做config,evaluate的結果直接傳回c++來用。支持了些基礎運算,變數,if/else,built-in function, import等基本功能。

感覺幹得還是挺爽的,雖然被大佬們嫌棄編譯原理學得不好,實現質量不夠高……

當年上課學編譯原理的時候,已經大四了,也沒咋聽,基本啥也沒學明白,就大概知道了一點dfa 遞歸下降之類的概念,project也是糊弄的。同事說我,現在等於領著工資,重做了一遍編譯原理的大作業,還有人幫我review代碼= =。自己慢慢實現一遍,發現其中有很多有趣的細節,又因為主要語法設計都參考的python,也更加明白了python的一些語言設計背後的原因。期間拿不準該怎麼實現好了,就還可以翻python的源碼,照著搬過來,特別runtime時候的一些處理,學了不少新知識。像我這種基本沒寫過多少c++的,等於又熟練了下c++,也是很值了……


?編程語言的數學分析

?從有限語言到無限語言的必經之路


很多人都說是裝13用的, 其實不然。 看level。 舉個我自己的栗子

大學的時候, 覺得這個玩意就是個雞肋, 覺得自己大約這輩子是不可能用到了。 因為學習成本很大, 用同樣的機會成本, 我可以學好多新語言, 實踐寫一些小程序練手, 豐富自己的Github什麼的, 看起來都比它有B格多了。

後來讀了研究生。。。還是讀的安全。 整天研究加密解密呀, 運行效率就變得非常重要, 同樣的程序, 優化和不優化, 那就是半小時還是一天的差距。 然後只能默默上網找以前教材, 再慢慢看看, 然後根據現在自己用的語言, 看看人家best practice 為什麼是best practice。。。

然後仰望高手們,突然理解人家為啥叫高手。 果然你大爺永遠是你大爺啊。。。。


讓你理解機器是如何理解高級語言的,更進一步的話,目前研究領域比較熱的自然語言處理裡面會用到,雖然不是直接用,但裡面的思想很有用。其實真寫個比現有的好的編譯器出來,大部分人估計沒這個功力;一般程序猿估計學了它能更好的優化自己的程序吧。


不知道牛校什麼樣。我畢業於一所普通211(計算機也不是學校強專業)。

編譯原理老師還是教授,他也不說編譯原理學了能幹嘛,還強調學了這個並不是讓你們去寫個編譯器。泛泛而談讓你知道編譯的過程方法理論,為以後學習工作打下基礎。於是,後面的講課也是為了理論而理論,什麼上下文無關文法,LL(1),就是一串字元讓你去匹配,也沒什麼編程作業,當然無聊。只是最後有個大作業,反正要用到lex,yacc之類。但是前面都無聊了,後面還會認真完成作業么?

我覺得,這門課一開始就應該定個目標,學這個,就是為了寫一個編譯器。編譯原理學了有什麼用?就是讓你知道怎麼入手去實現一個編譯器。


推薦閱讀:

從編譯原理上講,未來可能會出現既友好又高性能的高級語言嗎?
不學習編譯原理對於CS專業的學生有多大的損失?
C++ 中的左值、右值、左值引用、右值引用、引用分別是什麼,有哪些關係?

TAG:編譯原理 |