來咱們這個實驗室裏讀研的學生可能自歷來到這裏的第一天就以爲本身的命運很苦逼。他們讀本科時主修的是機械設計、製造以及自動化之類的專業,畢業時的簡歷上也頂可能是寫寫擅長 MS Word、PowerPoint、UGNX、AutoCAD 之類的應用軟件。他們有限的學習生涯裏,怎麼也不會想到來到這裏居然要首先從新學習 C 語言,而後還要學 C++,接下來還要學習 Python 或 Lua 什麼的,並且居然還不讓用 Windows,只能用連個 QQ 都沒有而且常常出故障的 Linux……html
在他們內心,編程彷佛並非多麼有趣的事,因此他們就以爲編程很難。對此我有同感,你們都會玩的 Windows 裏的挖雷與紙牌那樣的小遊戲,還有不少人會打的麻將,還有圍棋,這些事我以爲也挺難的。python
我曾經告訴他們,若是不會編程,那麼他們就很難解決本身的研究方向上的那些問題,所以也就不可能寫出有價值的論文,不可能順利的畢業拿到學位,不可能找到很好的工做……這種功利性的『威脅』,對於有些人會有點效用,可是若是沒有能力讓他們自發的對編程產生足夠的興趣,這對於任何一個『好爲人師』的人而言都是一種莫名其妙的羞辱。git
如今我試着去告訴他們,編程不只不難,並且會頗有趣,其中充滿着值得深思的東西,而這些深思對於咱們人生也會產生許多增益。因而,就有了這篇文章。程序員
不管你是否是程序猿,每一天你都在編程,每一天你都被編程。編程,就是設計一些步驟,組織這些步驟,讓這些步驟在當前環境中正確的運行,最終得出本身想要的結果。github
你的每一天都是在起牀、喝水、吃飯、工做、上廁所、娛樂、睡覺等步驟的有序組織下運轉的,你活在這個程序中,同時你在這個程序中爲改善本身的生活而制定各類計劃並努力去實現。web
機械設計,其實比編程還要編程。所謂的機械零件,就是數據結構。所謂的傳動機制,就是應用程序接口(API)。所謂發動機,就是程序的內核。你將零件裝配好,經過傳動機制將它們接駁到發動機上,因而你就創造出來一部機器,通上電或者打着火,就可讓它運轉起來。算法
編程比機械設計來的更爲簡單,你不須要常常給本身所編寫的程序添加潤滑油,也不須要去對每一個數據結構進行復雜的力學分析,更不須要關注這些數據結構是否嚴絲合縫的相互配合,至少目前的計算機軟件工程是這個樣子的,它不像機械工程學科那樣以堅實的物理定律爲基礎。機械的結構與運行規律老是可計算、可分析的,而軟件的結構與運行過程卻充滿着太多不嚴格的環節。這種不嚴格,卻給咱們營造了一個能夠發揮天賦或工科實踐經驗的空間。顯然,即便軟件工程存在着各類不嚴格,可是咱們卻可以經過編程模擬出機械工程的一切。事實上也是如此,現代的機械工程領域,軟件已經無處不在。編程
機械設計有不少精妙的『算法』,像縫紉機、槍械、發動機之類的機構,設計它們其實要比計算機世界裏的算法設計可貴多,並且這些機構對人類文明的發展每每可以產生巨大的推進做用。但願你不要所以愛上機械設計……學會編程,你會對機械設計的理解更爲深入。由於編程是將『設計』自己做爲一種智力活動而對待的。你能夠將機械工程領域的那些智力活動應用於編程,也能夠將編程中的智力活動應用到任何設計之中。小程序
正如 SICP 一書的序言所言,教育者、將軍、養分學家、心理學家以及父母們,他們作規劃,而士兵、學生以及某些社羣則被規劃。克服大型的問題,要通過一系列的規劃,其中大部分規劃會運做於現實之中,由於這些規劃老是與迫切處理的問題息息相關。若將規劃這件事情自己做爲一項智力活動來欣賞或研究,那麼就必須轉到計算機編程上面來。你須要閱讀與編寫計算機程序,並且要大量的作。程序是怎樣的,它們的功能是什麼,這些不過重要,重要的是它們的性能如何,它們之間可否精巧的相互配合從而構造更大規模的程序。segmentfault
學習編程以前,應該先問本身一個問題:我爲何要學習編程?不要打我……我知道大家是被逼着去學習編程的,那就不妨被逼着思考『我爲何要學習編程?』。
若是不知道答案,也沒有關係。反正這個問題與學習編程也沒有太大關係。其實,咱們已經作了很是多的不須要回答爲何的事了。咱們連『咱們爲什麼而存在』這樣的問題都不知道答案,卻依然糊里糊塗的活到了如今。
先推薦幾本入門書以及閱讀它們的方法。對於咱們而言,選對書很重要。國內科班出身的人所用的教科書對於咱們來講每每不合適,由於這些教科書可能比較適合在課堂上使用,課堂上老是會有一個能讀懂這些寫的挺糟糕的教科書的老師,他極有可能不會按照教科書裏的套路來說課,而教科書卻能夠扮演課堂筆記的角色。也就是說,大部分國產的編程書,它們比學生的課堂筆記強不了多少。非科班出身的人,沒有課堂,沒有老師,因此也就看不懂『課堂筆記』。好在,國外有一批優秀的書籍,課堂中的老師就在書中。
閱讀方法也挺重要,由於學習編程最不須要就是將一本講編程的書從頭讀到尾……對於非科班出身的人而言,編程不是考試,不必讓本身所掌握的知識去覆蓋全部的編程問題。人的精力極爲有限,大部分人終其一輩子,能在一兩個方向上有所建樹已經很對得起本身了,所以幾乎任何一本編程的書裏總會有些東西是你不必去看的。老是不要忘記,咱們是非科班出身,沒那麼多的時間去揮霍,而節省時間的最好的辦法就是隻取本身所需,前提是你的方向與目標是明確的。因此在讀書的過程當中,不要停下問本身,爲何要學習編程?
我推薦的第一本書是《計算機程序的構造和解釋》,英文名是《Structure and Interpretation of Computer Programs》,簡稱 SICP。英語閱讀能力好的同窗,能夠看英文版。中文閱讀能力好的同窗,能夠看中文譯本,裘宗燕老師的文字素養與翻譯的嚴謹程度基本上是可讚的(若是中文譯本某些地方看不懂了,能夠參照英文版)。這本書的閱讀,建議分如下三個階段:
閱讀前兩章,第一章是講計算過程的抽象方法,第二章是講基本數據類型(數據結構 + 運算)。這兩章的內容涵蓋了軟件世界的『九年制義務教育』的所有內容,所用的教學語言也是很是成熟且設計精巧的 Scheme 語言的一個很小的子集。學習這兩章內容的過程當中,能夠穿插着閱讀《Teach Yourself Scheme in Fixnum Days》的前 10 章,這份 Scheme 教程也有一份中文譯本。SICP 的習題,即便不去作,也應該把題目看一下,動腦子想想,判斷一下能不能作得出來。這些習題,在網絡上很容易找到答案。
複習 C 語言,教材用 Kernighan 與 C 語言之父 Ritchie 合寫的那本《C 程序設計語言》便可(學習期間,能夠了解一下 C99 與 C11 標準)。這個階段的設置,主要是面向咱們實驗室內部。由於咱們實驗室裏的同窗在本科階段一般是要修 C 語言這門課的,可是當時他們可能並未真正從學習編程的角度去學習,如今能夠經過第一階段由 Scheme 語言創建的編程觀念去從新認識一下 C 語言,只有這樣方能理解 C 語言的優勢與缺點,而且去思考如何充分發揮 C 的優點,而後用 Scheme 來彌補 C 的不足。藉助 GNU Guile 2,很容易實現 C 與 Scheme 複合編程。這個過程能夠穿插閱讀 Kernighan 寫的《程序設計實踐》。
閱讀 SICP 的第 3 章,而後再找一本講 C++ 的書,好比 C++ 世界中很是有名但我不覺得然的磚書《C++ Primer》,只學習基於類的數據抽象以及面向對象編程部分。SICP 的第 3 章闡述了面向對象編程與函數式編程兩種範式。從 SICP 中得到的面向對象編程,能夠在 C++ 的學習中獲得一些強化,至於 C++ 中的泛型編程,初學者沒必要過分深究,只需掌握 C++ 標準庫的基本用法,等具有必定的編程經驗以後,根據須要時另做打算。最後,記得將《Teach Yourself Scheme in Fixnum Days》剩下的內容看完。
C++ 的入門書,我更推薦《C++ Without Fear》,中文譯本叫《好學的 C++》,如今應該是第 2 版。之因此不推薦你們認爲是 C++ 四書五經之一的《C++ Primer》,是由於我總以爲它像一本事無鉅細的案頭手冊,比較適合那些已經有了編程經驗甚至 C++ 經驗的程序猿閱讀。我心目中真正好的教材應該像小說那樣,由一條或多條邏輯主線延展而成,這種教材對於非科班出身的人尤其重要。
對於大部分編程任務而言,上述書所涉及的知識已經足夠用了,並且上面的這幾本書也是很是耐讀的書,只要你不是那麼着急的將它們讀完,它們老是頗有趣。我很喜歡 SICP 與《程序設計實踐》這兩本書,由於太喜歡了,因此一直都不捨得把它們讀完。
注:會有人嘲笑,又有人又給你們推薦了連他本身都沒看完的書!事實上,SICP 與《程序設計實踐》這兩本書我讀完過。SICP 看了 1.x 遍(由於我對寫編譯器這種事不是很感興趣,因此第四章與第五章只是粗讀,前三章我看了不下三遍)。相似的,《程序設計實踐》也看了 1.x 遍。我之因此說『不捨得把它們讀完』,想表達的是每次重讀它們時,我都當本身沒讀過。
書是要看的,可是看書的過程當中最好開動你的雙手。因此,你不該該停下來問本身:爲什麼要學習編程?
我但願總有一天,你能給本身找到一個答案,那就是你想寫一個 XXX 程序。這個程序至少應該對你是有用,亦即它的主要功能不與你的系統裏的其餘程序存在着重複。若是你能明確這一點,那麼你所創造的程序就有了意義,你的學習就有了意義。
爲什麼要學習編程?由於你要創造一些歷來沒有的軟件,並且它可以幫助你作一些你認爲是很重要的事!凡是你認爲重要的事,對於不少人而言,頗有可能也是很重要的,所以你所創造的東西就能夠幫助更多的人,這意味着會有一些你可能不認識的人須要你,這就是你的價值所在。
編程是基於現實生活的創造。這種創造是漸進的,你在創造之初可能也沒法預料到結果會是如何,這是任何創造性活動的基本屬性。編程的實踐,應該將它做爲探索未知世界的智力活動,應該從書中跳出來,將本身從那些示例中得到的經驗用於解決現實中的問題。若是你以爲,現實中根本不存在什麼問題須要你去解決。那麼……請你回答一下『你爲什麼而存在』這個問題吧。
看書,是從前人正確的經驗中學習。實踐,是從本身的失敗中學習。既然決定要實踐了,因此仍是給本身找一些比較難走的路走走看吧,讓失敗多一些,讓失敗早一些。
以我我的比較感興趣的幾個東西爲例,能夠寫一個基於 TeX 的現代文學編程語言,經過它不只能夠歷練編程能力,也會對編譯原理中的語法分析環節有一些實際的認識。也能夠嘗試去寫一個三維幾何庫,可以完成凸包、Delaunay剖分以及 Voronoi 圖等計算,不求大而全,只求小而精,之後漫長的時間裏能夠慢慢的去改進它。還能夠去找一個本身喜歡的開源項目,去閱讀它的源代碼,瞭解它所用的項目構建系統,分析項目結構,試着去修改它的代碼……我如今最感興趣的是 LuaTeX。
假如你已經有了很是屢次的實踐上的失敗,而且你已經大體掌握了 Scheme 與 C/C++ 這樣的語言,那麼每一年學一門新的語言,這並不是難事。可能你會對網絡上常常發生的語言之戰以爲奇怪。
是問題決定了語言,是問題決定了編程範式,是問題決定了信仰。若是你能很明確的認識到這些,那麼你就不會陷入某種語言宗教的泥淖之中。對於許多事都是如此……搞機械的人,也常常信仰 UGNX,CATIA,PROE 這些『宗教』的……
若是非要給本身找一種信仰,那麼我信仰個人存在就是爲了解決問題的。
若是在我用的 Linux 系統上作一些自動化程度高一些的維護任務,我不會厭憎佶屈聱牙的 Bash 腳本,而是很是欣賞它像膠水同樣快速的將幾個原本是獨立運行的程序鏈接起來替我完成複雜的任務。
若是我要臨時的作一些文本處理工做,我能夠用 python 3,由於它對 UTF-8 支持的挺好,並且字符串庫功能齊備。若是隻是進行一些文本的替換,emacs 或 sed 之類現成的工具也夠用了。
若是我要寫一個嚴肅的程序,嚴肅到了它的生命可能要好久,那我會選擇一門成熟穩定的語言來實現它,即便用 C,我也不會煩棄它的繁瑣的代碼,我會盡力凝練程序中要實現的功能。
人生中原本就面臨着許多選擇,可是很是多的人在選擇以前並未認真的去考察本身面對的問題。
不過,對問題自己的考察,須要一套基本的工具集。沒有聽診器、手術刀或 X 光,再厲害的醫生也沒法分析人體的內部發生了什麼。對於編程而言,我認爲上述我推薦的書中所涉及的知識已經足夠用來洞察軟件世界的各類問題了,以此爲基礎,咱們只需再保持心態的開放,隨時汲取所需的知識就能夠了。例如,雖然上述幾本書沒有一本是講 Web 開發的,可是若是你熟悉 Scheme,就能夠發現 JavaScript、HTML 五、CSS 3 之類的語言並無超出 Scheme 的範疇,你能夠很快的就掌握它們。
解決問題須要算法。既然編程無處不在,那麼算法也是無處不在的。可是,若是隨便拿起一本講算法的書,隨便一本,可能都會讓你以爲頭昏腦脹。也許你會擔憂,連算法的書都看不懂,還怎麼寫程序?
當初我剛學習編程的時候,寫過二十四點、漢諾塔、八皇后、俄羅斯方塊之類的小程序。後來,在現實的項目裏,也寫過堆排序、快速排序、矩陣的 LU 與 SVD 分解、無向連通圖的最小生成樹及最短路徑之類的程序。可是如今,隨便拿一個讓我去實現,我仍是不得不去翻書看懂算法,而後再去寫程序……
我想說的是,若是你正在閱讀一本講算法的書,書裏有些算法或它的示例是你一時沒法看懂的,能夠跳過去。不少專門講算法的書裏,充斥着心智遊戲。若是你沒法將本身代入到這些遊戲的情境中,這個遊戲的玩法天然就是不明瞭的。如今看起來,這是很天然的事,然而當初我卻一遍又一遍的懷疑本身的智商,特別是看到網絡上不少人像喝白開水同樣的談論着這些心智遊戲,我一度懷疑,我不適合作編程方面的事。
幸虧,這個世界足夠穩定,以致於咱們不須要了解相對論與量子力學也可以很好的生活下去。大部分人,連牛頓力學都不須要了解……算法也是這樣,特別是如今已經存在了至關多的實現,例如幾乎任何一種編程語言的標準庫中都提供一維數據的快速排序算法的實現。基本上,只要是對現實中的問題很是重要的算法,你老是可以找到它們的既有實現,取而用之。
當你走在街上,那些高高矗立恢宏建築,建築工人建造它們的過程當中可曾用了極高心智的技術?編程,本質上也是如此,工程經驗的重要性大於心智。甚至在編程中,過多的運用心智,反而會拔苗助長。
我不是說學習算法沒有必要,我只是強調不要被一時難以理解的算法擋住你。你天生就擁有一些無比強大的算法,它們是窮舉、貪婪與分治,還有最強大的『演化』與『神經網絡』。那些專門講算法的書,只不過是是了很蹩腳的語言、符號以及示例將你天生的直覺刻畫出來而已。只要你在現實中遇到問題,你老是可以找到求解這個問題的方法,而不是隻有讀懂了某本講算法的書你才能解決這個問題。
不少算法書,都是我看不懂的。它們的第一章就是讓我複習數學概括法,第二章就是讓我學習算法的時間與空間複雜度分析……而我屬於對數學缺少直覺的人,對我而言,這些書的惟一價值就是故意不讓我去讀它。即便是我心目中的大神 Knuth 的傳世之做《計算機編程藝術》,它惟一的目的彷佛就是讓我以爲我不是搞藝術的。
好久以後,我在學校圖書館閒逛的時候,發現了《如何求解問題:現代啓發式方法》這本書,翻了翻,就開始嘆息,爲何一開始不知道這本書?
有時間與精力能夠閱讀一些專業性強一些的計算機理論的書籍,譬如操做系統原理、編譯原理、算法與數據結構之類。看不懂太專業的書,或者沒那麼多時間和精力,能夠看看計算機科學的一些科普著做。有本《通靈芯片》值得一看,薄薄的小冊子,三五天的業餘時間就能夠看完。有本《編碼:隱匿在計算機軟硬件背後的語言》,算是《通靈芯片》的增強版,也值得一看。有一本《深刻理解計算機系統》,以程序員的視角來看計算機的軟硬件系統,也是一本很好的書,不過就是要讀完它,須要一些耐心與時間,因此不必一次性看完。也能夠繼續將 SICP 的第4、五章看完。
雖然你的編程技能不會由於讀了這些講述計算機原理的書而日新月異,可是這些書可讓你理解你的程序是在一個什麼樣的世界裏運行的。雖然你不知道本身爲什麼而存在,可是你知道這個程序爲什麼而存在。你不只知道它爲什麼而存在,還知道它怎樣存在,而且也知道怎樣讓它更好的存在。這樣,也就不必在那些所謂的『XXX 箴言』、『XXX 之道』、『XXX 之禪』的書籍上浪費你有限的生命。
有時間,也能夠複習一下《黑客帝國》,它的導演雖然不是程序猿,但勝似程序猿。看完黑客帝國,也能夠看看 Steven Levy 寫的《黑客:計算機革命的英雄》。從技術層面躍遷到人文層面,也許那時你會對本身的人生有着更爲深入的認識。計算機,是人類爲本身創造出來的最好的一面鏡子。咱們如今沒有能力瞭解自身,可是咱們能夠製造與發展計算機來逐步瞭解本身。
有必要閱讀一些哲學、物理、生物之類的書籍,若是沒時間或者基礎也很差,能夠看科普書籍,並且我比較推薦看後者。看這些書,對編程技能沒有太直接的幫助,可是它們每每會讓你對身處的這個世界有所反思,甚至能夠得到一些新的認識,讓本身的意志更爲篤定。
若是從未想過去看哲學的書,我推薦一本 14 歲的少男少女就應該閱讀的《蘇菲的世界》。羅素的那本《西方哲學史》雖然出自他我的的視角,可是顯然咱們對哲學的理解也很難達到他那樣的高度,鑑於咱們也不是打算去在哲學上有所成就,《西方哲學史》足夠咱們看的了。我不認爲這個世界上真正存在『正確』的哲學。
複習物理。《費恩曼物理學講義》第一卷就很好,人類所能感知到的這個世界,費恩曼像講故事同樣的差很少一網打盡了。若是連費曼的書都看不懂,不妨看看《時間的形狀》+《量子物理史話》,它們是近年來在相對論及其以後的物理學方面中國人寫的很是優秀的科普書。還有一本是我大學時常常看的《從一到無窮大》,雖然年代已頗爲久遠,但依然不失爲極好的物理科普著做。
生物學,這門課在中學時是我最討厭的課程之一。由於我實在是看不懂書裏的插圖,鄉村中學連個顯微鏡與真實的標本都沒有,因此長期以來,我一直都是個生物盲。不少常見的花草樹木鳥獸蟲魚,我連它們的名字都叫不上來,更不要說它們具體屬於哪一個門綱目科屬種了。可是有一本生物學的書我仍是能看懂的——《漫畫玩轉遺傳學》,這是本很是好的遺傳學科普書。當時我是由於學習遺傳算法而買來的,結果從它從第一頁開始就把個人眼睛抓住了。
都看過,可是有一些也沒有看完。有些書是看完了,可是時間久了,有些遺忘,一直想找點時間再重讀一遍。
有些書是由於實在太好,不忍心一下都看完。這樣說,有些矯情,但事實就是如此。像《費恩曼物理學講義》,雖然有着物理學界小飛俠之稱的費恩曼已經將深邃的物理學變成了我可以讀懂的人類語言,可是一方面我不是專業研究物理學的人,我沒有必要趕進度似的將他的書完全讀完。學物理專業的人,可能也不會去將《計算機程序的構造和解釋》與《計算機編程實踐》看完的,不然他們就不會那麼酷愛 python 了。
有些書對我而言是由於太難,即便我以爲已經看完了,但過一段時間發現,跟沒看過是同樣的。這些書,我也只能歸類爲沒有看完的書。
凡是我看的書,都是我認爲在書中所涉及的方向上,做者比我走的更爲深遠。不過,我也不自卑,由於他們如今已經無法走了……
本文寫於一個深秋又寂寞的下午,目的只是爲個人小夥伴們學習編程指出一條道路。從 SICP 開始,可能有許多人以爲不靠譜,可是考慮到這些小夥伴一個一個都是研究生,考研期間通過了高數、線代、機率以及英語的『洗禮』,研一也會修數值分析與矩陣分析這兩門數學課。即便他們之前從未接觸過編程,可是他們的狀況,SICP 仍是挺適合他們的。若是他們連 SICP 的前兩章都搞不定,這隻能說明他們連 MIT 大一的學生都不如了……
對於我不知道底細又打算學編程的同窗,這篇文章可能不會太靠譜,因此我只能在題目中寫上『不負責任』。不過,文章中出現的這些書,我以爲還都是挺不錯的,有時間看一下,應該不是浪費時間。