偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

如何快速熟悉一門語言

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

[[142469]]

首先請原諒我這個標(biāo)題起的有點大,只是希望你能從我的經(jīng)歷中得到啟發(fā)。

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

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

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

在本科后半和研究生期間,有三年時間在研究FPGA,所以一直在使用Verilog和VHDL。它們是描述電路邏輯的語言,也就是說這些代碼最終會對應(yīng)到一個芯片的電路。但是與Erlang有很多非常相似的地方,很可能是因為它們都在描述并發(fā)系統(tǒng)。所以那個時候我就有了一個概念,語言是受限于所描述的系統(tǒng)的。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3. 調(diào)試

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

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

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

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

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

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

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

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

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

2022-02-27 14:45:16

編程語言JavaC#

2022-11-04 11:11:15

語言入職項目

2015-08-17 15:12:56

新技術(shù)語言框架

2019-11-18 11:00:58

程序員編程語言

2018-07-16 12:36:48

編程語言PythonJava

2015-07-29 09:58:29

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

2022-02-21 11:15:59

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

2024-06-27 09:00:00

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

2011-07-14 17:58:11

編程語言

2014-06-03 17:44:00

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

2017-04-07 10:45:43

編程語言

2013-07-26 10:23:04

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

2020-09-27 15:52:02

編程語言C 語言Python

2011-12-30 09:33:02

程序員語言

2023-02-08 07:35:43

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

2014-12-03 09:48:36

編程語言
點贊
收藏

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