當前位置:
首頁 > 最新 > 如何掌握所有的程序語言

如何掌握所有的程序語言

對的,我這裡要講的不是如何掌握一種程序語言,而是所有的……

很多編程初學者至今還在給我寫信請教,問我該學習什麼程序語言,怎麼學習。由於我知道標題問題的答案,所以總感覺這個問題是如此「低級」,一直沒來得及回復 :P 可是逐漸的,我發現原來不只是小白們有這個問題,就連美國大公司的很多資深工程師,其實也沒搞明白。

今天休閑活動進入第二個星期,稍微閑下來一點,我想來統一回答一下這個擱置已久的「初級問題」。這個話題貌似曾經寫過,然而現在我想把它重新寫一遍。因為通過跟很多人的交流,我對自己頭腦中的(未轉化為語言的)想法,有了更精確的表達。

如果你存在以下的種種困惑,那麼這篇文章也許會對你有所幫助:

你是編程初學者,不知道該選擇什麼程序語言來入門。

你是資深的程序員或者團隊領導,對新出現的種種語言感到困惑,不知道該「投資」於那種語言。

你的團隊為使用哪種程序語言爭論不休,發生各種宗教鬥爭。

你追逐潮流採用了某種時髦的語言,結果兩個月之後發現深陷泥潭,痛苦不堪……

雖然我已經不再過問這些世事,然而無可置疑的現實是,程序語言仍然是很重要的話題,這個情況短時間內不會改變。程序員的崗位往往會要求熟悉某些語言,甚至某些奇葩的公司要求你「深入理解 OOP 或者 FP 設計模式」。對於在職的程序員,程序語言至今仍然是可以爭得面紅耳赤的宗教話題。它的宗教性之強,以至於我在批評和調侃某些語言(比如 Go 語言)的時候,有些人會本能地以為我是另外一種語言(比如 Java)的粉絲 :P

其實呢,我並不是任何一種語言的粉絲,我甚至不是 Yin 語言的粉絲 ;) 對於任何從沒見過的語言,我都是直接拿起來就用,而不需要經過學習的過程。看了這篇文章,也許你會明白我為什麼可以達到這個效果。理解了這裡面的東西,每個程序員都應該可以做到這一點。嗯,但願吧。。。 :P

重視語言特性,而不是語言

很多人在乎自己或者別人是否「會」某種語言,對「發明」了某種語言的人倍加崇拜,為各種語言的孰優孰劣爭得面紅耳赤。這些問題對於我來說都是不存在的。雖然我寫文章批評過不少語言的缺陷,在實際工作中我卻很少跟人爭論這些。如果有其它人在我身邊爭論,我甚至會戴上耳機,都懶得聽他們說什麼 ;) 為什麼呢?我發現歸根結底的原因,是因為我重視的是「語言特性」,而不是整個的「語言」。我能用任何語言寫出不錯的代碼,就算再糟糕的語言也差不了多少。

任何一種「語言」,都是各種「語言特性」的組合。打個比方吧,一個程序語言就像一台電腦。它的牌子可能叫「聯想」,或者「IBM」,或者「Dell」,或者「蘋果」。那麼,你可以說蘋果一定比 IBM 好嗎?你不能。你得看看它裡面裝的是什麼型號的處理器,有多少個核,主頻多少,有多少 L1 cache,L2 cache……,有多少內存和硬碟,顯示器解析度有多大,顯卡是什麼 GPU,網卡速度,等等各種「配置」。有時候你還得看各個組件之間的兼容性。

這些配置對應到程序語言裡面,就是所謂「語言特性」。舉一些語言特性的例子:

變數定義

算術運算

for 循環語句,while 循環語句

函數定義,函數調用

遞歸

靜態類型系統

類型推導

lambda 函數

面向對象

垃圾回收

指針算術

goto 語句

這些語言特性,就像你在選擇一台電腦的時候,看它裡面是什麼配置。選電腦的時候,沒有人會說 Dell 一定是最好的,他們只會說這個型號裡面裝的是 Intel 的 i7 處理器,這個比 i5 的好,DDR3 的內存 比 DDR2 的快這麼多,SSD 比磁碟快很多,ATI 的顯卡是垃圾…… 如此等等。

程序語言也是一樣的道理。對於初學者來說,其實沒必要糾結到底要先學哪一種語言,再學哪一種。曾經有人給我發信問這種問題,糾結了好幾個星期,結果一個語言都還沒開始學。有這糾結的時間,我都可以把他糾結過的語言全部掌握了。

初學者往往不理解,每一種語言裡面必然有一套「通用」的特性。比如變數,函數,整數和浮點數運算,等等。這些是每個通用程序語言裡面都必須有的,一個都不能少。你只要通過「某種語言」學會了這些特性,掌握這些特性的根本概念,就能隨時把這些知識應用到任何其它語言。你為此投入的時間基本不會浪費。所以初學者糾結要「先學哪種語言」,這種時間花的很不值得,還不如隨便挑一個語言,跳進去。

很多初學者不了解,一個高明的程序員如果開始用一種新的程序語言,他往往不是去看這個語言的大部頭手冊或者書籍,而是先有一個需要解決的問題。手頭有了問題,他可以用兩分鐘瀏覽一下這語言的手冊,看看這語言大概長什麼樣。然後,他直接拿起一段例子代碼來開始修改搗鼓,想法把這代碼改成自己正想解決的問題。在這個簡短的過程中,他很快的掌握了這個語言,並用它表達出心裡的想法。

在這個過程中,他會問這樣的問題:

這個語言的「變數定義」是什麼語法,需要「聲明類型」嗎,還是可以用「類型推導」?

它的「類型」是什麼語法?是否支持「泛型」?泛型的 「variance」 如何表達?

這個語言的「函數」是什麼語法,「函數調用」是什麼語法,可否使用「預設參數」?

……

注意到了嗎?上面每一個引號裡面的內容,都是一種語言特性(或者叫概念)。這些概念可以存在於任何的語言裡面,雖然語法可能不一樣,它們的本質都是一樣的。比如,有些語言的參數類型寫在變數前面,有些寫在後面,有些中間隔了一個冒號,有些沒有。

這些實際問題都是隨著寫實際的代碼,解決手頭的問題,自然而然帶出來的,而不是一開頭就抱著語言手冊看得仔仔細細。因為掌握了語言特性的人都知道,自己需要的特性,在任何語言裡面一定有對應的表達方式。如果沒有直接的方式表達,那麼一定有某種「繞過方式」。如果有直接的表達方式,那麼它只是語法稍微有所不同而已。所以,他是帶著問題找特性,就像查字典一樣,而不是被淹沒於大部頭的手冊裡面,昏昏欲睡一個月才開始寫代碼。

掌握了通用的語言特性,剩下的就只剩某些語言「特有」的特性了。研究語言的人都知道,要設計出新的,好的,無害的特性,是非常困難的。所以一般說來,一種好的語言,它所特有的新特性,終究不會超過一兩種。如果有個語言號稱自己有超過 5 種新特性,那你就得小心了,因為它們帶來的和可能不是優勢,而是災難!

同樣的道理,最好的語言研究者,往往不是某種語言的設計者,而是某種關鍵語言特性的設計者(或者支持者)。舉個例子,著名的計算機科學家 Dijkstra 就是「遞歸」的強烈支持者。現在的語言裡面都有遞歸,然而你可能不知道,早期的程序語言是不支持遞歸的。直到 Dijkstra 強烈要求 Algol 60 委員會加入對遞歸的支持,這個局面才改變了。Tony Hoare 也是語言特性設計者。他設計了幾個重要的語言特性,卻沒有設計過任何語言。另外大家不要忘了,有個語言專家叫王垠,他是早期 union type 的支持者和實現者,也是 checked exception 特性的支持者,他在自己的博文里指出了 checked exception 和 union type 之間的關係 :P

很多人盲目的崇拜語言設計者,只要聽到有人設計(或者美其民曰「發明」)了一個語言,就熱血沸騰,佩服的五體投地。他們卻沒有理解,其實所有的程序語言,不過是像 Dell,聯想一樣的「組裝機」。語言特性的設計者,才是像 Intel,AMD,ARM,Qualcomm 那樣核心技術的創造者。

合理的入門語言

所以初學者要想事半功倍,就應該從一種「合理」的,沒有明顯嚴重問題的語言出發,掌握最關鍵的語言特性,然後由此把這些概念應用到其它語言。哪些是合理的入門語言呢?我個人覺得這些語言都可以用來入門:

Scheme

Java

Python

JavaScript

那麼相比之下,我不推薦用哪些語言入門呢?

Shell

PowerShell

AWK

Perl

PHP

Basic

Go

總的說來,你不應該使用所謂「腳本語言」作為入門語言,特別是那些源於早期 Unix 系統的腳本語言工具。PowerShell 雖然比 Unix 的 Shell 有所進步,然而它仍然沒有擺脫腳本語言的根本問題——他們的設計者不知道他們自己在幹什麼 :P

採用腳本語言學編程,一個很嚴重的問題就是使得學習者抓不住關鍵。腳本語言往往把一些系統工具性質的東西(比如正則表達式,Web 概念)加入到語法裡面,導致初學者為它們浪費太多時間,卻沒有理解編程最關鍵的概念:變數,函數,遞歸,類型……

不推薦 Go 語言的原因類似,雖然 Go 語言不算腳本語言,然而他的設計者顯然不明白自己在幹什麼。所以使用 Go 語言來學編程,你不能專註於最關鍵,最好的語言特性。

掌握關鍵語言特性,忽略次要特性

為了達到我之前提到的「融會貫通」,一通百通的效果,初學者應該專註於語言裡面最關鍵的特性,而不是被次要的內容分心。我發現很多編程培訓班和野雞大學的編程入門課,往往一來就教學生如何使用 printf 列印「Hello World!」,進而要他們記憶 printf 的各種「格式字元」的意義,要他們實現各種複雜格式的列印輸出,甚至要求列印到文本文件里,然後再讀出來……

可是殊不知,這種輸出輸入操作其實根本不算是語言的一部分,而且對於掌握編程的核心概念來說,都是次要的。有些人的 Java 課程進行了好幾個星期,居然還在布置各種 printf 的作業。學生寫出幾百行的 printf,卻不理解「變數」和「函數」是什麼,甚至連算術語句和循環語句都不知道怎麼用!這就是為什麼很多初學者感覺編程很難,我連 , , 的含義都記不住,還怎麼學編程!

然而這些野雞大學的「教授」頭銜是如此的洗腦,以至於被他們教過的學生(比如我女朋友)到我這裡請教,居然罵我凈教一些沒用的東西,學了連 printf 的作業都沒法完成 :P 你別跟我將 for 循環,函數什麼的了…… 可不可以等我幾個月,等背熟了 printf 的用法再學那些啊?

所以你就發現一旦被壞老師教過,這個程序員基本就毀了。就算遇到好的老師,她也很難糾正過來。

自己動手實現語言特性

在基本學會了各種語言特性,能用它們來寫代碼之後,下一步的進階就是去實現它們。只有實現了各種語言特性,你才能完完全全的擁有它們,成為它們的主人。否則你就只是它們的使用者,你會永遠做語言創造者們的僕人。

有個大師說得好,完全理解一種語言最好的方法就是自己動手實現它,也就是自己寫一個解釋器來實現它的語義。但我覺得這句話應該稍微修改一下:完全理解一種「語言特性」最好的方法就是自己親自實現它。

注意我在這裡把「語言」改為了「語言特性」。你並不需要實現整個語言來達到這個目的,因為我們最終使用的語言特性。只要你自己實現了一種語言特性,你就能理解這個特性在任何語言里的實現方式和用法。

舉個例子,學習 SICP 的時候,大家都會親自用 Scheme 實現一個面向對象系統。用 Scheme 實現的面向對象系統,跟 Java,C++,Python 之類的語言語法相去甚遠,然而它卻能幫助你理解任何這些 OOP 語言裡面的「面向對象」這一概念。它甚至能幫助你理解各種面向對象實現的差異,這種效果是你直接學習 OOP 語言也得不到的。

類似的特性還包括類型推導,類型檢查,惰性求值,如此等等。我實現過幾乎所有的語言特性,所以任何語言在我的面前都是可以被任意拆卸組裝玩弄的玩具,而不再是凌駕於我之上,高高在上的神聖。

總結

寫了這麼多,重要的話重複三遍:語言特性,語言特性,語言特性,語言特性!不管是初學者還是資深程序員,應該專註於語言特性,而不是整個語言的「品牌」。只有這樣才能達到融會貫通,拿起任何語言幾乎立即就會用,並且寫出高質量的代碼。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

全局單例換一種姿勢使用
YI Tunnel「看」一眼即可結賬,傳統零售業迎來「無人店」時代
歡迎來到後 ASO 時代
papi醬將出任分答papi社區社長 79元可入社半年
為什麼 Reddit 選擇了 TypeScript?

TAG:推酷 |

您可能感興趣

有哪門語言是所有優秀程序員都應該無差別掌握的?
對於沒有編程經驗的人,R 語言是否很難掌握?
如何選擇大數據的編程語言
如何使用多種編程語言而又不失理智
如何根據一個人的語言判斷其是否有抑鬱癥狀?
你想知道的,目前最火的編程語言有哪些?
如何選擇適合自己的編程語言?
比利時為何沒有自己的語言?
語言胎教該如何操作,有哪些注意事項?
淺談如何精通一門非母語的語言
情感中語言的魔力,為什麼要用肯定的語言彼此讚賞?
為什麼說方言是最具有精髓的語言?
我們與機械臂的共同語言,是肢體語言
如何用鏡頭語言講好故事
沒有語言的怪人
真正的語言是無聲的
如果「時間」也是一種編程語言,世界該多有趣?
如果編程語言是飛機
網路流行語究竟是如何摧毀你的語言能力的?
語言暗示的力量遠超過你的想像!請注意與孩子溝通的語言藝術!