譯者 | 晶顏
審校 | 重樓
盡管我們很喜歡編程語(yǔ)言,但不可否認(rèn)它們常常像件“緊身衣”,讓人感覺(jué)束縛和窒息。它們是一組復(fù)雜的語(yǔ)法規(guī)則,如果我們破壞了它們——即使只有一次——編譯器就會(huì)開(kāi)始發(fā)出錯(cuò)誤消息。定義每一件小事都有規(guī)則,例如命名變量的最佳方式或如何縮進(jìn)代碼。語(yǔ)言設(shè)計(jì)者聲稱這些約束是一個(gè)特性,而非一種缺陷。
多年來(lái),聰明的開(kāi)發(fā)人員已經(jīng)想出了很多方法來(lái)用他們自己獨(dú)特的風(fēng)格編寫代碼。預(yù)處理器就是彌補(bǔ)這一差距的關(guān)鍵,它會(huì)在代碼編譯之前進(jìn)入管道,以修復(fù)所有奇怪的扭曲和保持編碼樂(lè)趣的個(gè)人風(fēng)格。
預(yù)處理器其實(shí)并不是什么新鮮事物。像C這樣的語(yǔ)言多年來(lái)一直依賴于它們。但是最近它們變得越來(lái)越流行,因?yàn)殚_(kāi)發(fā)人員創(chuàng)造了更多的表達(dá)方式,讓程序員可以隨心所欲地編寫軟件。到了編譯的時(shí)候,所有這些獨(dú)特的風(fēng)格都會(huì)被悄悄地刪除和替換,讓最終版本能夠符合該語(yǔ)言的細(xì)致規(guī)則。
為了幫助程序員擺脫束縛,這里列出了一些預(yù)處理代碼的方法。其中包括特定于語(yǔ)言的預(yù)處理器,這些預(yù)處理器可以彌合數(shù)據(jù)科學(xué)家和開(kāi)發(fā)人員之間的差距,甚至可以將美式英語(yǔ)轉(zhuǎn)換為更適合大洋彼岸同事的語(yǔ)言。
LESS和SASS
CSS(層疊樣式表)作為前端入門的三駕馬車之一,其作用之大、地位之重可想而知。然而,CSS不像其他編程語(yǔ)言能夠定義變量、常量、條件語(yǔ)句等,也不能提供重用性,對(duì)后期的代碼維護(hù)也十分復(fù)雜。針對(duì)以上問(wèn)題,CSS預(yù)處理器應(yīng)運(yùn)而生。
LESS是一個(gè)使用廣泛的CSS預(yù)處理器,它通過(guò)引入變量、嵌套規(guī)則、混合、運(yùn)算和函數(shù)等動(dòng)態(tài)語(yǔ)言的特性,極大地?cái)U(kuò)展了CSS的功能,同時(shí)顯著減少了CSS的代碼量,提高了代碼的可讀性和可維護(hù)性。誕生于2007年的SASS則是最早且最成熟的CSS預(yù)處理器,比CSS多出很多功能,包括變量、嵌套、運(yùn)算、混入、繼承、指令、函數(shù)等。
SASS與LESS的主要區(qū)別在于SASS需要Ruby環(huán)境,日常開(kāi)發(fā)使用SASS插件(Live Sass Compiler或其他)(運(yùn)行在服務(wù)器端);LESS則基于JavaScript,需要引入LESS.js來(lái)處理代碼輸出CSS(客戶端運(yùn)行,也就是瀏覽器運(yùn)行)。此外,兩者在變量符、輸出風(fēng)格以及條件語(yǔ)句等方面也有諸多不同。不過(guò),這兩種工具都可以讓你以程序員的觸覺(jué)和敏感性來(lái)清理看似無(wú)窮無(wú)盡的CSS布局選項(xiàng)列表。
AbsurdJS
有些人喜歡一致性,喜歡使用一種特定的語(yǔ)言。如果你是JavaScript的粉絲,并且想用它的力量來(lái)制作你的CSS,那么AbsurdJS將是你的理想預(yù)處理器。
AbsurdJS是一個(gè)用JavaScript編寫的能夠支持HTML和CSS的預(yù)處理器。你可以使用AbsurdJS把JavaScript、JSON、YAML轉(zhuǎn)換成HTML和CSS。它支持Nodejs和瀏覽器,并且一個(gè)額外的好處是提供流行編程語(yǔ)言的語(yǔ)法,如JavaScript。
正如其他預(yù)處理器一樣,它具有如文件導(dǎo)入、變量、媒體查詢冒泡算法、 混合、嵌套選擇器等諸多功能,可被用作純JavaScript以使用變量來(lái)生成CSS文件或者實(shí)現(xiàn)其他的動(dòng)態(tài)功能。
像LESS和SASS一樣,這個(gè)預(yù)處理器也可以讓你像程序員而不是設(shè)計(jì)師那樣思考。
Bython
一些開(kāi)發(fā)人員喜歡使用大括號(hào)來(lái)定義代碼塊,而另一些人則更喜歡按空格鍵和tab鍵。Python是為喜歡良好縮進(jìn)的程序員設(shè)計(jì)的。現(xiàn)在它變得更加強(qiáng)大和普遍,一些喜歡花括號(hào)的人可能也想要使用Python庫(kù)和工具。Bython作為一個(gè)預(yù)處理器,將允許你保留大括號(hào)和Python庫(kù)。你只需要像平常一樣編寫代碼,剩下的全部交由Bython來(lái)完成。它會(huì)自動(dòng)將花括號(hào)替換為縮進(jìn),這樣你就不必按空格鍵了。
Pypreprocessor
長(zhǎng)期以來(lái),C語(yǔ)言為C程序員提供了使用#ifdef等預(yù)處理語(yǔ)句對(duì)代碼做出復(fù)雜決定的機(jī)會(huì),#ifdef可以打開(kāi)和關(guān)閉大塊代碼。現(xiàn)在Python程序員可以用Pypreprocessor做同樣的事情,Pypreprocessor是一個(gè)動(dòng)態(tài)庫(kù),允許你使用標(biāo)志和元變量使代碼隨意消失和重新出現(xiàn)。
TypeScript
JavaScript最初是為需要向主要由HTML構(gòu)建的網(wǎng)站添加短代碼塊的Web程序員設(shè)計(jì)的。如果你不想拼寫變量的類型,也沒(méi)什么大不了的,因?yàn)镴avaScript代碼塊很小,而且易于理解。不過(guò),這種情況已經(jīng)發(fā)生了變化,現(xiàn)在許多開(kāi)發(fā)人員使用成千上萬(wàn)行JavaScript構(gòu)建復(fù)雜且非常動(dòng)態(tài)的站點(diǎn)。
考慮到JavaScript語(yǔ)言本身的局限性,TypeScript作為一個(gè)折衷方案應(yīng)運(yùn)而生。TypeScript是微軟開(kāi)發(fā)的一個(gè)開(kāi)源的編程語(yǔ)言,通過(guò)在JavaScript的基礎(chǔ)上添加靜態(tài)類型定義構(gòu)建而成。TypeScript通過(guò)TypeScript編譯器或Babel轉(zhuǎn)譯為JavaScript代碼,可運(yùn)行在任何瀏覽器,任何操作系統(tǒng)。
TypeScript仍然可以接受泛型JavaScript,這意味著你添加的所有類型信息都是可選的。TypeScript的預(yù)處理階段會(huì)在能找到錯(cuò)誤的時(shí)候仔細(xì)檢查,然后輸出一些通用JavaScript引擎可以處理的程序。一些最流行的JavaScript框架(比如Angular)現(xiàn)在都依賴于TypeScript來(lái)實(shí)現(xiàn)強(qiáng)類型編程(strong typing,對(duì)變量的類型有嚴(yán)格的要求,類型錯(cuò)誤在編譯時(shí)就能發(fā)現(xiàn))。
CoffeeScript
對(duì)于每一個(gè)渴望用C風(fēng)格語(yǔ)法編寫代碼的Python程序員來(lái)說(shuō),都渴望能夠?qū)崿F(xiàn)自由和簡(jiǎn)單地編寫程序。CoffeeScript就是這一訴求的答案。它現(xiàn)在有許多變體,如ToffeeScript、Civet、 Storymatic、CoffeeScript II: The Wrath of Khan,以及其他十幾種變體。所有這些語(yǔ)言都讓我們免去了舉起右手小指按分號(hào)鍵的繁瑣工作。它們還提供了一些簡(jiǎn)潔的特性,比如異步語(yǔ)法和精細(xì)的元編程機(jī)制。結(jié)果就是代碼更簡(jiǎn)潔,標(biāo)點(diǎn)符號(hào)更少了,至少在CoffeeScript程序員看來(lái),這更容易閱讀。
Handlebars和Pug
現(xiàn)代代碼通常包含許多文本塊,其中包含最終人類用戶的消息。它們通常充滿了許多插入和自定義。像Handlebars和Pug這樣的模板系統(tǒng)有助于加快編寫這些人類可讀文本塊的速度,而無(wú)需編寫粘合字符串所需的低級(jí)代碼。你只需編寫文本,該模板系統(tǒng)就會(huì)處理將所有部分拼接在一起的雜務(wù)。
AWK
Unix命令行工具是處理純文本的最簡(jiǎn)單和最強(qiáng)大的工具之一。AWK以它的三位創(chuàng)建者Alfred V. Aho、Peter J. Weinberger和Brian W. Kernighan的名字命名,它將許多命令鏈接在一起,用于從行中提取數(shù)據(jù)并對(duì)其進(jìn)行排序和過(guò)濾。程序員還會(huì)使用它在主程序?qū)朐紨?shù)據(jù)之前清理/處理管道中的原始數(shù)據(jù)。
Vapour
R是一門主要由統(tǒng)計(jì)學(xué)家創(chuàng)造的強(qiáng)大語(yǔ)言,這些統(tǒng)計(jì)學(xué)家通常像數(shù)學(xué)家而非計(jì)算機(jī)程序員那樣思考。這并不是一件壞事,但它可能成為使用R中所有優(yōu)秀庫(kù)的障礙,這些庫(kù)在編程設(shè)計(jì)中缺乏一些偉大的進(jìn)步。Vapor作為一個(gè)預(yù)處理器,將允許R用戶像程序員一樣思考,特別是像那些喜歡使用類型系統(tǒng)來(lái)捕捉錯(cuò)誤和強(qiáng)化結(jié)構(gòu)的程序員一樣思考。Vapou的開(kāi)發(fā)人員表示,它仍處于早期的alpha階段,所以他們可能會(huì)增加新的功能和調(diào)整語(yǔ)法。最終目標(biāo)是讓工具隨著用戶的需求快速發(fā)展。
Spiffing
并不是所有說(shuō)英語(yǔ)的人都以同樣的方式使用英語(yǔ),尤其是在不同的大陸和文化中。Spiffing是一種可以將用美式英語(yǔ)編寫的代碼翻譯成英式英語(yǔ)的預(yù)處理器。這聽(tīng)起來(lái)有點(diǎn)傻,但這并不意味著它沒(méi)有用處或無(wú)法彌合文化鴻溝。如果它流行起來(lái),也許有一天,開(kāi)發(fā)人員會(huì)構(gòu)建出預(yù)處理器,這樣它就能把相當(dāng)直接的美式語(yǔ)言轉(zhuǎn)換成更含蓄的英式語(yǔ)言。例如,我們可以使用perchance- else語(yǔ)法代替if-then語(yǔ)句。
Linting preprocessors
并不是所有的預(yù)處理器都會(huì)轉(zhuǎn)換代碼。有些預(yù)處理器會(huì)跟在我們后面尋找遺漏的漏洞。最初的Unix命令行工具“lint”已經(jīng)發(fā)生變化,現(xiàn)在在許多語(yǔ)言開(kāi)發(fā)堆棧中都可看到它作為預(yù)處理器的身影。這些linting工具(或linters)會(huì)修復(fù)格式、強(qiáng)制命名約定,甚至修復(fù)一些語(yǔ)法和語(yǔ)義錯(cuò)誤。流行的版本包括適用于Ruby代碼的RuboCop,適用于Python的Pylint以及適用于JavaScript的ESLint(ECMAScript)。
用于文檔的預(yù)處理器
一些預(yù)處理器還會(huì)產(chǎn)生可運(yùn)行代碼以外的東西。Sphinx、MkDocs和Doxygen等工具能夠分析文件,并直接從代碼創(chuàng)建一組帶注釋和交叉引用的文檔文件。這些工具設(shè)計(jì)用于多種語(yǔ)言,但幾乎所有語(yǔ)言都有自己的官方預(yù)處理器。流行的例子包括Javadoc、Rustdoc、Godoc和JSDoc。
集成數(shù)據(jù)報(bào)告的預(yù)處理器
數(shù)據(jù)科學(xué)家不僅僅會(huì)說(shuō)R語(yǔ)言。他們還用人類語(yǔ)言編寫復(fù)雜的數(shù)據(jù)報(bào)告,其中充滿了R創(chuàng)建的圖表、表格和圖形。多年來(lái),數(shù)據(jù)科學(xué)家不僅為R創(chuàng)建了復(fù)雜的預(yù)處理器,還為排版語(yǔ)言LaTeX創(chuàng)建了復(fù)雜的預(yù)處理器??茖W(xué)家用R和人類語(yǔ)言編寫所有內(nèi)容,然后預(yù)處理器將其分解,將計(jì)算指令發(fā)送給R,將排版指令發(fā)送給LaTeX。與此同時(shí),它會(huì)調(diào)整各個(gè)部分,這樣R生成的圖片就會(huì)出現(xiàn)在你文檔中的正確位置。然后,LaTeX將它們折疊成最終的PDF,該P(yáng)DF由文件的人類語(yǔ)言部分生成。它在完成所有這些工作的同時(shí),還會(huì)組織頁(yè)面引用和插圖編號(hào)以保持一致。
此類預(yù)處理有各種不同的選擇,具備不同的優(yōu)勢(shì)和強(qiáng)項(xiàng)。R Markdown是普通Markdown的一種變體,可用于合并計(jì)算和數(shù)據(jù)分析。它還可以合并來(lái)自Python或SQL等語(yǔ)言的結(jié)果來(lái)生成幻燈片、文檔、書籍和網(wǎng)站。Knitr和它的前身Sweave是兩個(gè)緊密結(jié)合的預(yù)處理器,都得到了Rstudio的良好支持。對(duì)于那些想要將Python與LaTeX合并的人,還有Pweave可供選擇。有一天,或許還會(huì)出現(xiàn)一個(gè)元版本,將所有這些合并到一個(gè)大的預(yù)處理器中。
使用AI進(jìn)行預(yù)處理
所有的預(yù)處理器都需要一些配置。那么,為什么不讓人工智能來(lái)做呢?有些人已經(jīng)將他們的預(yù)處理器上傳到了LLM(大型語(yǔ)言模型),并要求它修復(fù)所有錯(cuò)誤。在一個(gè)例子中,一些精打細(xì)算的人在開(kāi)發(fā)者告訴他們重寫Agda編譯器來(lái)實(shí)現(xiàn)更新需要花費(fèi)超過(guò)100萬(wàn)美元后勃然大怒。有人想出了一個(gè)好主意,從他們的代碼庫(kù)中上傳所有500多個(gè)文件到Anthropic的Sonnet-3.5。瞧!一眨眼的功夫,編譯器就被轉(zhuǎn)換成了TypeScript。開(kāi)發(fā)人員報(bào)告稱,大多數(shù)代碼在沒(méi)有干預(yù)的情況下均運(yùn)行良好。LLM并不完美,但它們讓我們更接近這樣一個(gè)世界:我們只要揮揮手,機(jī)器就會(huì)像變魔術(shù)一樣為我們做事。
原文標(biāo)題:14 great preprocessors for developers who love to code,作者:Peter Wayner