如何從零開始學一門程序語言?

今天一大早排隊挂號給孩子看病,耽擱了,現在才發。

說實話,『能花錢的,就不要花時間』是篇即興之作,本該隨著時間被有限的聽眾漸漸淡忘。但沒想到前有 @老趙 微博轉發,後有知乎日報鼎力提攜,這篇文章火得一塌糊塗,一下子把我推到了風口浪尖。我其實想委婉地表達一個意思:程序員的時間很寶貴,只要有能用合理價格買來的用來提高效率的產品和服務,就不要花時間找免費或廉價的替代品。但顯然還是被不少人誤讀。不少人質疑的焦點放在了:『你是有錢了,可我們是屌絲,買不起正版軟體,正版圖書,盜版不也一樣用么?』我沒想到隨手舉的一個買正版軟體,kindle圖書的例子引起這麼大反響,可這爭論似乎偏離了我文章的主旨 —— 正版盜版之爭不是該文討論的重點。其實每個人心裡應該都有一桿天平,左邊放著『合理的價格』,右邊是你的時間。天平怎麼調整,在乎你,不在乎我的幾行文字。

程序君再次重申,『程序人生』傳遞的是作者個人當下的思想,你可以不信,但切不可全信。:)

善者不辯。程序君修行還不夠啊。:(

言歸正傳。

最近的留言中,『如何從零開始學一門程序語言?』這個問題問到的頻次最多。我本不該回答,因為我不在行 —— 我現在已經回想不起十幾年前究竟是怎麼學第一門(有實際意義的)語言的。而我現在學習一門新語言的經驗對入門者來說也許並不合適。

仔細想了想,還是決定趕鴨子上架,說說看。Again,絕對個人意見,望能拋磚引玉。首先,『興趣是最好的老師』這樣類似的話我先晾到一邊,你自己補。這些東西一講你都知道,看完你除了能點個贊之外,似乎還是對學程序語言沒感覺。而且這種話說給學習任何東西似乎都有效。

如何選擇語言?

我的第一門實用型的語言是Visual Basic。看了一段時間的windows編程,在各種句柄,消息循環以及繁複的MFC中迷失後,VB讓我見識到了簡單,直接了當,以及文檔(MSDN)的重要性。學習的門檻是個大問題,有些語言(及其背後的框架)沒有一定的基礎最好不要碰。

當然,語言總是在發展,現在在dotnet框架下的VB已經失去了那種簡單直接的美。

第一門語言最好選擇帶如下屬性的語言:

  • 語法簡單,結構明晰,寫出來的代碼相對簡潔明了
  • 有完善的生態系統,尤其是文檔
  • 語言最好提供REPL(Read-Evaluate-Print-Loop)和introspection
  • 開源社區(如github)有足夠多的樣本代碼
  • ...

以python為例,稍微解釋一下第三條。python的shell(python或ipython)提供了一個語法和庫函數的試驗場,對初學這門語言來說幫助很大。想弄通python的數據結構,在shell下練習半小時基本就懂了。另外,在shell里隨時可以對任何函數,類庫做introspection(內省)—— 通過 help,dir,type,inspect(庫)等深入到被調者內部了解其行為,這就進一步降低了初學者的門檻。寫C代碼的時候,遇到不太明白怎麼使用的函數時,要麼看其源碼,要麼找文檔,但在python里,方便的內省工具可以隨時隨地幫助你。

補充一句,這兩個語言沒有可比性,我僅僅拿來舉個例子。也許有人會說我可以用gdb做內省啊,但那已經不是一個層面的解決之道,也不是初學者入門時能掌握的。

第一條不用太解釋,沒人一開始就喜歡複雜吧?第二條和第四條當你學習時,有什麼參考資料,及當你遇到問題時,可以尋求到什麼幫助。你可以從某語言的官網上了解其社區文檔的完備性,從stackoverflow和github上了解其生態系統和社區力量的強弱。

如果非要讓我很主觀地推薦,第一門語言我推薦python,它滿足上面的所有要求(ruby,scala等也都可以考慮)。

看到這,也許你會問,有REPL豈不是不把大多數static typing的語言給排除在外了?對!

因為標題是從零開始學,學的過程中的互動(和shell),學習者不斷構建信心很重要。compiler介入只會給這個階段的學習帶來不必要的負擔。

如何學習?

學一門語言,要從語言的歷史思想入手。

從語言的歷史中,我們可以了解到語言誕生時的各種因素,以及在之後發展過程中的種種選擇。除此之外,你要了解大概該語言的社區中在時間軸上都出過什麼樣的產品。這些都會加深你對語言的理解和認同感。

學習語言的思想(哲學)很重要,這體現在語言的設計,語法,甚至整個社區的行為。將一個數字轉化成字元串,在python里你大概會這麼做:

In [1]: str(10)nOut[1]: 10n

但在ruby里你應該這麼做:

irb(main):001:0> 10.to_sn=> "10"n

如果你將其視為語法而死記硬背,那事倍功半。ruby的哲學是,純粹的OO,告訴object做什麼事,而非對object做什麼事。

對比ruby和python兩種語言很有意思。ruby作者從smalltalk和perl的影響很大,所以ruby里一切都是對象(smalltalk),做一件事可以有多種方法(perl)。ruby的作者賦予了ruby靈活的控制權,讓你可以改變系統的行為(比如可以open一個類庫中的class修訂),又有點像lisp。

python從Abc這門教學語言(Algol)中繁衍出來,對純粹的OO並不感冒,因此代碼可以混用面向過程和面向對象。也許是教學語言的基因,python強調做一件事用一種最清晰的方式完成("There should be one - and preferably only one - obvious way to do it."),所以社區里有人說某個實現是"pythonic",說明這個實現清晰,簡潔,符合python之道。當然python還吸收了很多其它語言的優點,如list comprehension(haskell),applying function to list(lisp)等等。

了解了歷史和思想,你會對語言的行為有一個比較合理的解釋,學習起來也比較容易舉一反三。當然作為第一門語言,你肯定不知道那麼多其它語言的名字,很多我也不知道,但可以wiki一下,當拓展/延伸閱讀了。

之後就是看文檔書籍,看各種網上的視頻教程來學習語言的語法和各種庫。這個階段比較枯燥(REPL能稍稍降低這種枯燥)。不要看教科書學語言,教科書上的習題大多和生活中的問題無關,不要試圖去寫什麼鴿籠問題,八皇后的代碼。你在學程序語言,不是在做思維訓練或是數學。

注意選擇書籍的時候盡量選擇該語言作者(或者名家)的書,比如ruby該看『松本行弘的程序世界』,python的 "Programming Python"(python作者做的序),erlang看 "Programming erlang - software for a concurreny world",等等,他們會將很多知識和思想匯入書中。

另外還有一本無關語言,但關於編程要義的書非常值得一看:『冒號課堂』。國內的作者多寫點這樣的書,少做點語法介紹、類庫介紹的大磚頭,將是中文圖書的幸事。

過了語法關之後,有兩個學習方法:

  • 以練代學
  • 和社區互動
  • 以教代學

以練代學是找個有意思的項目,甩開膀子邊寫代碼邊學。駕校里永遠無法讓你真正學會開車,但你上路後的一周內,你就基本掌握了駕駛的全部技巧;每天都在各種複雜路況上開一個月,你就是老手了。學語言也是這個理。

學習的過程中總有困惑,多在google groups和stackoverflow裡面尋找答案。如果實在找不到,用符合社區標準的方式發問。這也是一個累積經驗的過程。

以練代學的基礎上,最好教一個不會但又想學的人這門語言,或者找一些志同道合的人一起學。有時候我們的思維會受定勢的影響,過濾好多頭腦中的『傻』問題。別人一個看上去很簡單的問題也許會重新觸動你的神經,讓你好好思索那些被自己視為『簡單』的問題的答案。

不過,教別人某門語言的機會不常見,但在社區里看看別人有什麼問題,嘗試回答,也實踐了以教代學。

如何進階?

當你基本能比較隨手用某個語言寫出簡單的應用後,你該考慮回過頭來補補那些之前忽略的環節,重新審視這門語言:

  • 它的類型系統有什麼特點?
  • 內存管理模型是什麼樣的?
  • 語言和庫分別有什麼並發的手段?
  • 對范型的支持?
  • 異常處理的機制和社區約定俗成的方式是什麼?
  • 對OOP都有哪些支持?
  • 對FP都有哪些支持?
  • 如何進行元編程?
  • 與其他語言的互操作(比如C)是怎麼樣的?
  • 語言有什麼天然的限制?
  • ...

在這個審視的過程中,不斷把基礎知識補齊 —— 這些都是快速掌握下一門語言的基礎。

你也許還應該找些比較有意思的源代碼,看看別的程序員都是怎麼寫代碼的。讀優秀的代碼就像讀一本好書,仔細咂吧,其樂無窮。

代碼寫累了,看看名家的書,修鍊一下思想。『黑客與畫家』,『松本行弘的程序世界』,『程序員修鍊之道』等一眾書都可看看。

比如說程序員修鍊之道里寫到:

You shouldnt be wedded to any particular technology, but have a broad enough background and experience base to allow you to choose good solutions in particular situations.n

我覺得這就是做軟體應該有的態度 —— 沒有最完美的語言,只有最合適的工具。

結語

說了這麼多,似乎跟沒說一樣。學習語言本就是一個因人而異的東西,沒有放之四海皆準的教條。還是那句話:修行靠個人!

如果你對本文感興趣,歡迎訂閱公眾號『程序人生』(搜索微信號 programmer_life)。每天一篇原汁原味的文章,早8點與您相會。

送給看到這裡的要學C的程序員一份小福利,戳下面的鏈接閱讀:Learn C The Hard Way

推薦閱讀:

Promise: 給我一個承諾,我還你一個承諾
世界盃情緣
就這樣,在波特蘭跑完了人生第二個馬拉松
奇博士的管理課 - 激勵
[技術與產品] Bower & Brunch

TAG:迷思 | 『冒号课堂』 | LearnCTheHardWay |