自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何快速熟悉一門語言

移動(dòng)開發(fā)
編程一直是我的愛好,我最喜歡的是和圖形圖像有關(guān)的部分,但是過去幾年里我學(xué)的一直是和電子有關(guān)的內(nèi)容。我最初上手編程是通過數(shù)學(xué)軟件Mathematica,它本身也是一個(gè)強(qiáng)大的函數(shù)式編程語言,于是順手學(xué)習(xí)了Haskell/Scheme/Prolog等FP語言。后來修了一門分布式系統(tǒng)的課程,為了設(shè)計(jì)分布式系統(tǒng)我學(xué)習(xí)了Erlang,因?yàn)橐彩呛瘮?shù)式編程,且語法很多借鑒了Prolog,所以使用了很長時(shí)間。

[[142469]]

首先請(qǐng)?jiān)徫疫@個(gè)標(biāo)題起的有點(diǎn)大,只是希望你能從我的經(jīng)歷中得到啟發(fā)。

我看到不少?zèng)]有編程背景的人也收藏了這篇文章,我會(huì)把太學(xué)術(shù)的地方注釋一下。

編程一直是我的愛好,我最喜歡的是和圖形圖像有關(guān)的部分,但是過去幾年里我學(xué)的一直是和電子有關(guān)的內(nèi)容。我最初上手編程是通過數(shù)學(xué)軟件Mathematica,它本身也是一個(gè)強(qiáng)大的函數(shù)式編程語言,于是順手學(xué)習(xí)了Haskell/Scheme/Prolog等FP語言。后來修了一門分布式系統(tǒng)的課程,為了設(shè)計(jì)分布式系統(tǒng)我學(xué)習(xí)了Erlang,因?yàn)橐彩呛瘮?shù)式編程,且語法很多借鑒了Prolog,所以使用了很長時(shí)間。

FP指functional programming,是以函數(shù)作為基礎(chǔ)的語言,與之相對(duì)應(yīng)的是imperative language,指令式語言。指令式的語言的程序逐條執(zhí)行指令,每個(gè)指令都會(huì)影響到某些存儲(chǔ)單元的數(shù)據(jù),或者是設(shè)備。函數(shù)式語言則相對(duì)抽象,用操作(函數(shù))本身代替了被操作的對(duì)象,且函數(shù)本身還能用別的函數(shù)來描述,是一個(gè)很自洽的體系。Haskell和Scheme都是經(jīng)典的FP語言。

在本科后半和研究生期間,有三年時(shí)間在研究FPGA,所以一直在使用Verilog和VHDL。它們是描述電路邏輯的語言,也就是說這些代碼最終會(huì)對(duì)應(yīng)到一個(gè)芯片的電路。但是與Erlang有很多非常相似的地方,很可能是因?yàn)樗鼈兌荚诿枋霾l(fā)系統(tǒng)。所以那個(gè)時(shí)候我就有了一個(gè)概念,語言是受限于所描述的系統(tǒng)的。

FPGA 叫做Field Programmable Gate Array (現(xiàn)場可編程門陣列)。我們都知道集成電路的信號(hào)都是0和1,也就是高低點(diǎn)位,而這0和1又能控制其他的電路通斷,這就是數(shù)字電路的基本原理。我們知道內(nèi)存里面存的也都是0和1,于是就有很天才的人想到了能不能用一個(gè)內(nèi)存條作為開關(guān),來控制一大堆電路的通斷呢?這個(gè)東西后來實(shí)現(xiàn)了,一個(gè)叫Ross Freeman的人最終實(shí)現(xiàn)了商用的FPGA,并且創(chuàng)建了Xilinx公司,建立了一個(gè)大產(chǎn)業(yè)。(然而Ross Freeman在實(shí)現(xiàn)了FPGA沒多久后就因癌癥去世了,沒有看到他發(fā)起的大產(chǎn)業(yè),這是題外話。)

簡單來說,一個(gè)FPGA就相當(dāng)于一個(gè)結(jié)構(gòu)可以不斷變化的電路,很像人的神經(jīng)網(wǎng)絡(luò)。目前FPGA的使用途徑主要集中在金融領(lǐng)域的高頻交易,但是Google已經(jīng)構(gòu)建起一個(gè)FPGA farm,進(jìn)行深度學(xué)習(xí),分析Google的數(shù)據(jù)中心中存儲(chǔ)的所有數(shù)據(jù)(還有Youtube的視頻),在不同的數(shù)據(jù)之間尋找隱含的關(guān)聯(lián)。如果有一天Google搜索能完全理解自然語言,那一定是FPGA的功勞。

研究生后半和博士的前兩年,我在做無線傳感器網(wǎng)絡(luò),無線傳感器節(jié)點(diǎn)使用了一個(gè)神奇的叫做Contiki的操作系統(tǒng)。這個(gè)系統(tǒng)的特點(diǎn)是用了protothread,就是介于process和thread之間的概念,scheduler切換進(jìn)程時(shí)只會(huì)記住當(dāng)前的指令指針,而不會(huì)保存context,于是所有的內(nèi)容必須得存儲(chǔ)在全局變量中。這么做的原因是protothread實(shí)現(xiàn)很簡單,且無線傳感器用的處理器內(nèi)存只有2K。

無線傳感器網(wǎng)絡(luò)基本就是我們常說的物聯(lián)網(wǎng),每個(gè)節(jié)點(diǎn)的主要構(gòu)成是一個(gè)小的無線收發(fā)芯片和一個(gè)小處理器。由于功耗限制,這些芯片的性能都不能太高,所以能夠在這些芯片上設(shè)計(jì)一個(gè)操作系統(tǒng)(還是多任務(wù)的)實(shí)在是心靈手巧的人才做得到。(當(dāng)然,現(xiàn)在隨便拿出來一個(gè)處理器,速度都比當(dāng)年開發(fā)UNIX的PDP-11快出好多)

博士的最后一年在做軟件無線電,就是通過USRP+GNURadio來實(shí)現(xiàn)OFDM通信,并且找到當(dāng)前WiFi(802.11a/g/n)中可以改進(jìn)的地方。但是回國之后就不再做硬件了,還是回到了最鐘愛的圖形圖像。但是圖形和圖像本身也是兩個(gè)極為不同的領(lǐng)域,一般來說圖形(計(jì)算機(jī)圖形學(xué))指的是如何顯示圖像,而圖像(計(jì)算機(jī)視覺)指的是如何識(shí)別和處理圖像,二者只有在很小的領(lǐng)域擁有交集。目前做的兩個(gè)創(chuàng)業(yè)項(xiàng)目分別和WebGL及二維碼識(shí)別有關(guān)。

在過去幾年中做了這么多項(xiàng)目,跨度都非常大。由衷感覺到知識(shí)是無窮無盡的,懂得多不如學(xué)的快,而最關(guān)鍵的是你能很快地找到切入點(diǎn),并且迅速建立自信。

0. 為什么要快速熟悉一門語言/框架

你已經(jīng)見過網(wǎng)上有很多人在為哪種語言或那種框架而爭論,在這之前你也聽說過中國人要不要學(xué)英語這種問題。語言自始至終都有兩種功能,第一種是從實(shí)用主義出發(fā)的功能,就是與人交際,你每掌握一門新的語言,就能理解使用這門語言的人或者物件,并進(jìn)一步掌控。如果你能講VHDL,你就能控制FPGA,如果你會(huì)講CUDA或OpenCL,你就能控制GPU,如果你會(huì)講kext腳本,你就能控制蘋果各種產(chǎn)品的設(shè)備,如果你能自如地使用英文搜索,你積累關(guān)于計(jì)算機(jī)方面的知識(shí)的速度會(huì)比你同齡同資歷的程序員快很多。

第二種功能是從情感出發(fā)的功能,就是使用同一種語言的人在尋求彼此認(rèn)同。當(dāng)你在外漂泊多年遇到老鄉(xiāng)時(shí)的感覺,或是突然回到家鄉(xiāng)發(fā)現(xiàn)大家講話你全能聽得懂,甚至包括一些微妙的用其他語言難以表達(dá)的事物或情境的時(shí)候,那感覺會(huì)很不一樣。程序員容易在自己使用的語言當(dāng)中找到歸屬感,并且通過自己熟悉的語言來建立自信。這樣會(huì)使人驕傲,并且阻斷繼續(xù)學(xué)習(xí)的道路。

語言本身沒有任何好壞,一種新的語言的誕生總是和它使用的環(huán)境有關(guān)。如果和使用環(huán)境無關(guān)的語言,即使本身的設(shè)計(jì)再優(yōu)雅也不會(huì)流行,如Haskell及Lisp一干dialects,反之亦然,如JavaScript。你要學(xué)一門語言或框架,是為了做一些東西,是為了和一同使用這門語言的人共事,所以任何時(shí)候都不要評(píng)價(jià)語言或者框架。畢竟這一切都是人創(chuàng)造的,而人總是有局限的。最終要達(dá)到的目的是為了對(duì)機(jī)器的掌控,與人的交流,而不是自我陶醉。

1. 搭建調(diào)試平臺(tái)

在看任何書之前,先去按文檔把自己機(jī)器上的調(diào)試環(huán)境搭好。你再懂得這門語言的歷史,再懂的這門語言的使用場景,甚至把語言的關(guān)鍵字API全都記得滾瓜爛熟也沒用,這就和你認(rèn)為背單詞對(duì)學(xué)好英語有貢獻(xiàn)一樣可笑。成功,或者成熟掌握一項(xiàng)技能很少有能夠量化的指標(biāo),如果硬要找一個(gè)指標(biāo)來衡量你離成功或熟練有多近,那最接近的是你在實(shí)踐中失敗過多少次。

2. 研究最基本的數(shù)據(jù)結(jié)構(gòu)

幾乎在所有語言中最基本的數(shù)據(jù)結(jié)構(gòu)是形如Array/List一類帶有標(biāo)記的順序結(jié)構(gòu),我們姑且稱之為『表』。樹/圖/Dictionary/矩陣都可看作表的延伸。在數(shù)據(jù)庫中有大量對(duì)字典的增刪改查(CRUD)操作,允許你往表里堆不同的東西,結(jié)構(gòu)也可以非常多樣化。然而在圖形和圖像中,則含有大量矩陣操作,操作的對(duì)象是非常整齊的數(shù)據(jù)。

在寫代碼的時(shí)候有一個(gè)通過實(shí)踐總結(jié)出的原則,很少出現(xiàn)在教科書內(nèi),就是代碼塊之間(代碼塊是我臨時(shí)想到的詞,因?yàn)樵诓煌琾aradigm里語言的單位是不同的,在Java中是類,在Python中是對(duì)象,在JS中是prototype,在Erlang中是process等等)傳遞的信息應(yīng)當(dāng)是盡可能簡單和通用的數(shù)據(jù)結(jié)構(gòu),而最好不是很復(fù)雜的對(duì)象。就是說一個(gè)代碼塊收到了這樣的信息,經(jīng)過一些操作變成了結(jié)構(gòu)復(fù)雜,容量也很大的信息。那么這個(gè)代碼塊應(yīng)當(dāng)把這個(gè)信息簡化到盡可能接近簡單通用的數(shù)據(jù)結(jié)構(gòu),才算作是完成了一件事。如果這個(gè)代碼塊返回了一坨巨大的數(shù)據(jù),而另一個(gè)代碼塊接收的也是一坨巨大的數(shù)據(jù),那么這個(gè)代碼塊的功能劃分是有問題的。

這是為什么UNIX選擇以文本文件作為基礎(chǔ)的信息組織單位,并且所有的文件都允許以文本文件的方式來處理,并且明確地提出一個(gè)程序應(yīng)該能夠輸出文本,所以你能夠看到UNIX內(nèi)部的程序都會(huì)輸出stderr,使你通過dmesg就可以查看它們的足跡。由于以文本文件為基礎(chǔ),UNIX對(duì)正則表達(dá)式異常重視(grep, sed, awk, perl, ...)也就不足為奇了。這些個(gè)小部件統(tǒng)稱coreutils,掌握這些小部件才算能理解*x系 (當(dāng)然包括OS X) 的強(qiáng)大威力?,F(xiàn)在幾乎所有的以表為單位的語言都開始支持map/reduce/filter等操作,并很自然地引入lambda function,也正是因?yàn)樗鼈儤O大地拓展了表結(jié)構(gòu)的表達(dá)能力。

在JavaScript中,Array是基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),但是和JSON兼容的Object也是,Array和Object可以無差別替換,但是在JS引擎中,Array和Object的表達(dá)是完全不同的,通常Array是被優(yōu)化過的。如果Array的index不是從0開始連續(xù)遞增的整數(shù)(比如中間有一個(gè)元素是undefined),那么它存儲(chǔ)時(shí)就會(huì)被退化為Object,查找也要以O(shè)bject匹配key的方式進(jìn)行,這樣就會(huì)慢很多。

在OpenCV中,由于大部分的操作都和圖像有關(guān),所以cv::Mat就成了基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),矩陣的各種操作,包括轉(zhuǎn)置,求逆,合并與拆分,SVD等等。OpenCV對(duì)這個(gè)基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)進(jìn)行了很多優(yōu)化,使得運(yùn)行時(shí)的I/O開銷最小。譬如現(xiàn)在有對(duì)Intel處理器的TBB支持,TBB將程序的并發(fā)性顯式地表達(dá)了出來,當(dāng)然這部分機(jī)制又被OpenCV封裝了起來,比如進(jìn)行RANSAC操作時(shí)(要在一堆點(diǎn)中擬合出一條直線或者橢圓)需要在一個(gè)很大的點(diǎn)集中尋找,不斷進(jìn)行SVD解方程求模型的系數(shù),有了TBB,就可以使SVD操作并發(fā)執(zhí)行,大大提高性能。所以你首先要做的便是去熟悉各種與Mat有關(guān)的操作。

GNURadio是一個(gè)軟件無線電框架,它需要一個(gè)無線收發(fā)機(jī)進(jìn)行直接上下變頻,CPU通過程序?qū)Υa進(jìn)行編碼和解碼操作,這些事以前都是由硬件電路完成的,現(xiàn)在全都變成CPU指令,對(duì)于延遲就變得非常敏感。在GNURadio中有一套類似TBB的機(jī)制,將操作變?yōu)椴煌哪K,譬如FFT和IFFT,功率譜密度等等,而在這些模塊之間的接口則不光定義了數(shù)據(jù)類型,還包括最大和最小允許寫入的數(shù)據(jù)速率。

不同領(lǐng)域的語言相差很大,語言背后的核心概念相差可能更大,在3D圖形領(lǐng)域以矩陣操作為主,在某些語境下矩陣不是個(gè)很方便的表達(dá)方法,于是有了歐拉角和四元數(shù)(Quaternion),這些notation更簡明,但是也更不易理解。在2D圖像領(lǐng)域有些很神奇的算法,譬如Hough找直線找橢圓,RANSAC擬合平面,SIFT/FAST來找圖像的特征,在無線通信領(lǐng)域這一切又不一樣。但是無論哪個(gè)領(lǐng)域,都總是有一套最基礎(chǔ)的和領(lǐng)域之外的人交流的途徑,這就是基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)。

3. 調(diào)試

之前提到從基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)開始,是因?yàn)閷?duì)基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)的操作結(jié)果最容易預(yù)料到。當(dāng)代碼開始變得復(fù)雜時(shí),編譯器或者運(yùn)行環(huán)境就有可能無法很明確地告訴你錯(cuò)在哪里,有的時(shí)候是不報(bào)錯(cuò),有的時(shí)候沒有報(bào)對(duì)錯(cuò)(這個(gè)更誤導(dǎo))。

編譯器或運(yùn)行環(huán)境的反饋是最佳的理解計(jì)算機(jī)的信息,但是因?yàn)榉N種原因這信息可能不夠全面。如果僅僅依靠這些信息會(huì)浪費(fèi)你大量的時(shí)間,因此你需要設(shè)法讓你的代碼向你提供更多的信息。在寫C代碼的時(shí)代,我會(huì)用大量的printf來幫助我,主要有以下的功能:

  1. 打印運(yùn)行結(jié)果
  2. 打印if-else的控制流語句中代碼流到了哪個(gè)岔路口
  3. 打印循環(huán)是在什么條件下終止的

之所以出現(xiàn)bug原因無非有三種:

  1. 你對(duì)你要做的事情不夠了解
  2. 你對(duì)你使用的語言的語法特性不夠了解
  3. 你對(duì)你使用的函數(shù)/庫/框架不夠了解

所以出現(xiàn)了bug之后,你首先要確定你的bug大概來自上述問題中的哪一種,當(dāng)然很有可能的就是這幾種都包含。在這種情況下錯(cuò)誤會(huì)十分難查找。我們先考慮第二種,對(duì)于語法特性如果還不夠了解,請(qǐng)回到基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)那一關(guān),做各種各樣簡單的示例,在那一關(guān)解決掉所有的語法問題。如果是第三種,那么你需要認(rèn)真閱讀文檔和源碼。

如果你對(duì)你做的事情不夠了解,這涉及到一個(gè)很微妙很有趣的事情。我來告訴你,人類編程的能力最終是由他駕馭母語的能力決定的。如果一個(gè)人無法和另一個(gè)人講清楚一件事情要如何做,那么他自然無法向計(jì)算機(jī)描述清楚一件事情。所以走上編程道路的理科生,數(shù)理思維再突出,當(dāng)年拉下的語文課也會(huì)成為日后的短板。相反,如果你觀察美國各種技術(shù)發(fā)布會(huì)的presentation,或是長期為開源項(xiàng)目作貢獻(xiàn)的程序員,他們的口才和文筆都不差。

那么如何查找錯(cuò)誤呢?在代碼得到錯(cuò)誤結(jié)果,或是沒有正常的運(yùn)行,或者沒有通過編譯的時(shí)候,有一個(gè)地方已經(jīng)不符合你的預(yù)期,使它出現(xiàn)了錯(cuò)誤。你可以從最后一個(gè)符合預(yù)期的結(jié)果開始查找,或是沿著最終的錯(cuò)誤向后回溯。當(dāng)然最好的就是你能為每一個(gè)關(guān)鍵的步驟都提供詳細(xì)的信息,以便你之后的修改?,F(xiàn)在大部分的單元測(cè)試框架都鼓勵(lì)人,甚至要求人這么做。這不是很高端很酷炫的技術(shù),而是充分考慮到人本身思維的各種缺陷。

責(zé)任編輯:倪明 來源: 簡書
相關(guān)推薦

2022-02-27 14:45:16

編程語言JavaC#

2022-11-04 11:11:15

語言入職項(xiàng)目

2015-08-17 15:12:56

新技術(shù)語言框架

2019-11-18 11:00:58

程序員編程語言

2018-07-16 12:36:48

編程語言PythonJava

2011-07-14 17:58:11

編程語言

2015-07-29 09:58:29

快速學(xué)習(xí)

2022-02-21 11:15:59

編程語言后端開發(fā)

2024-06-27 09:00:00

人工智能編程語言軟件開發(fā)

2014-06-03 17:44:00

快速學(xué)習(xí)新技術(shù)

2013-07-26 10:23:04

2017-04-07 10:45:43

編程語言

2017-04-07 16:49:00

語言程序編程

2012-09-04 11:20:31

2021-07-09 06:48:30

語言Scala編程

2012-03-28 09:40:40

JavaScript

2011-12-30 09:33:02

程序員語言

2023-02-08 07:35:43

Java語言面向?qū)ο?/a>

2020-09-27 15:52:02

編程語言C 語言Python

2014-12-03 09:48:36

編程語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)