我們為什麼需要語法高亮

語法高亮(syntax highlighting)如今非常流行:除了尚未入門的菜鳥和超凡入聖的大師,幾乎所有程序員的代碼編輯界面都是花花綠綠的一片。我造的 elvish 也以自帶語法高亮為賣點。

不過當一種東西無處不在時,我們就要質疑它到底是真有必要,還是只是無意義的傳統。前貝爾實驗室員工、Plan 9 和 Go 語言的設計者 Rob Pike 經常在推特上告誡眾人說,放棄語法高亮有清心寡欲之功效,並可使碼力指數增長(並不)。

兩年前有一片文章 Coding in Color(推薦閱讀)說,語法高亮所「高亮」的語言關鍵字(while return)、操作符(+-*/)等等,其實都是很「顯然」的東西,不需要再高亮了。畢竟,哪個合格的程序員不對她的程序語言中有哪些關鍵字、哪些操作符了如指掌呢?所以,不妨拋棄語法高亮,給每個變數上不同的顏色,這樣一來各個變數在何處使用一目了然,可以讓程序結構更加明晰;同時也有助於發現變數名中的筆誤。作者稱這種高亮為「語義高亮」。

我當時覺得他們說的都好有道理一時不知怎麼反駁。我在實現 elvish 的語法高亮時也充滿了負罪感,總覺得這是在向無謂的傳統妥協。直到最近,我才發現語法高亮到底高在哪裡。

階乘的定義,用數學記號寫出來是這樣(為了和程序信息量一致,加上了類型標註):

f (n {:} mathbb{N}) {:} mathbb{N} = begin{cases}n1 & text{if } n = 0 nn cdot f(n-1) & text{otherwise}nend{cases}

用程序寫出來就是:

int f(int n) {n if (n == 0) {n return 1;n } else {n return n * f(n-1);n }n}n

大多數人都會同意,和數學公式比起來,這代碼簡直沒法看……

int f(int n) {n if (n == 0) {n return 1;n } else {n return n * f(n-1);n }n}n

加上高亮是不是好多了?但是即使加上高亮,還是遠遠不如數學公式美觀。

對照一下公式和代碼就會發現,公式其實也是有「語法高亮」的。例如變數如 n 是斜體,集合如 ? 是「黑板粗體」(blackboard bold);「條件控制」的結構則乾脆用橫跨兩行的花括弧表示,簡直不能更醒目。

相比之下,代碼則局限在 ASCII 里可憐的幾十個符號中。更糟糕的是,代碼還是等寬的,即使是花括弧這種鬼魅狂狷的符號也得局限在固定大小的方框中。缺少傳統的排版手段,就只能靠顏色來彌補了:這就是為什麼我們需要語法高亮。

那既然如此,為什麼設計語法的人不多引入一些符號和排版手段,讓程序語言也能搞得賞心悅目呢?答案是,為了排版出之前那一段公式,我其實要寫這麼一坨東西:

f (n {:} mathbb{N}) {:} mathbb{N} = begin{cases}n1 & text{if } n = 0 nn cdot f(n-1) & text{otherwise}nend{cases}n

讀者是開心了,但是天天讓我寫這個我要狗帶……

即使不用 TeX 這種排版語言,改用所見即所得的編輯器來排版,效率也遠遠比不上錄入之前那一段 C 程序。因此不引入高級的排版手法和奇怪的符號,實為方便錄入的必要之舉。

至於等寬字體,則的確是傳統的力量了。讀過 The C++ Programming Langauge 的同學會知道,這本書全書用比例字體排代碼,習慣之後的確比等寬字體要舒服不少。(哪位有書的同學拍張照片給我啦。)

Rob 之所以不需要語法高亮,也是因為他的編輯器 Acme 支持比例字體:

(可惜 Rob 大概不會成為 elvish 貢獻者……)

這個字體里花括弧形狀詭異也不是偶然。


推薦閱讀:

為什麼黑暗之魂3創建了一個新角色之後存檔尺寸沒有發生變化?
Node.js 十問
大學理科生零基礎自學計算機和編程有哪些書籍和方法比較好?
關於C++11中移動語義的一個問題?何時移動構造函數會被調用?

TAG:编程 | 文本编辑器 |