數心開物工作室於6月1日開源釋出了一門中文程式語言——青語言,並在開源中國、部落格園等技術社群釋出了相關新聞。與預期的一樣,中文程式設計作為一個極具爭議性的話題,該新聞一經發布,便收穫了較多的關注和評論,其中包括大量的差評,甚至惡評。作為一個開源專案,我們並不介意這樣的討論,也不熱衷於與反對者網路對線,所以基本沒有對這些差評做出迴應。開源專案的發展需要依賴社群的助力,因此我們願意接受社群的批評和建議,但為了避免對青語言的誤解,我們希望通過本文,對青語言的語法設計進行一些說明。
1、青語言可讀性差?
關於這一點,我們認為可能更多的是因為程式設計習慣的原因,而非青語言設計的問題。
首先,青語言的語法設計主要參考了JavaScript。JS是一門成熟且簡單的主流程式語言,青語言在語法設計上沒有做過多的創新,就是希望在做好程式設計啟蒙的同時,能夠讓使用者快速地切換到主流的程式語言開發中。基於這一點,我們認為青語言在語法設計上不存在大的邏輯問題,目前也暫時沒有收到語法Bug的相關反饋,當然這更可能是因為很少有人願意深入瞭解青語言。
其次,範例程式中大部分涉及圖形介面程式設計,這一功能是通過內建標籤型別來實現的,大概類似於JSX。並且標籤型別使用的是書名號《》來表示,這一點可能會讓不熟悉標示語言的讀者感到困惑,又或者是單純的不太適應書名號。
事實上,青語言從一開始設計的時候,就著重考慮了程式碼的可讀性,尤其是我們的目標使用者主要是青少年、兒童,此時程式碼的可讀性就尤為重要。由於語法核心參考了Lisp,所以青語言的語法元素非常簡單,主要分為變數名、函數名、關鍵字和符號、資料字面量,程式碼可讀性需要我們能夠方便地區分出這些語法元素。在這幾種語法元素中,關鍵字和符號是固定的,資料字面量通過格式區分,符合日常使用習慣。剩下的就是變數和函數,在大多數程式語言中變數和函數名是不進行區分的,但事實上這兩者有著本質區別,變數表示某個資料,而函數表示一組操作。所以,為了提高程式碼可讀性,青語言的語法設計上做了如下要求:
以#開頭的是變數名
以@開頭的是函數名
這樣的設計從語法實現的角度來說並不是必需的,而且可能在語法上有囉嗦之嫌,這算是青語言為了提高程式碼可讀性在語法設計上做的取捨。
而這樣設計的好處就是能夠快速區分變數和函數,例如在JS中出現
a.b
這個時候我們可以知道a是一個物件,但是無法判斷b是物件的屬性還是方法。而在青語言中則是做了明確的標記:
#a#b ;這是物件a裡的屬性b
#a@b ;這是物件a裡定義的函數b
青語言對變數名和函數名的限定非常寬鬆,只要使用的是語法符號外的非空字元,都可以支援。雖然我們在範例程式中都使用了中文變數名和函數名,但事實上完全支援使用英文,並不是像一些評論所說的完全排斥英文。使用#和@符號進行標記在簡單變數名中顯得囉嗦,但是在路徑中能夠替代成員操作符,並且路徑格式更符合中文組詞的方式。
採用這一設計的另一個好處則體現在編輯器提示的實現上。為了提高程式設計效率,我們在釋出青語言的同時提供了青語言編輯器,雖然還不夠智慧,但基於以上提到的語法元素分類的方式,我們通過十分簡單的邏輯,提供了基於上下文的程式碼提示。
2、青語言使用的符號雜亂?
這一問題主要受限於中文字型的顯示,當然這個問題完全可以通過輸入法設定固定英文符號的方式解決,但是在考慮到語言受眾以及實際的顯示效果,我們認為這是完全能夠適應的,不存在明顯的優劣之分,更多的是習慣問題。
下面舉個簡單的例子,可能不太正確,僅作討論。在主流的程式語言中,通常使用逗號作為列表項的分隔標記例如JS中我們呼叫一個函數並傳入參數列:
f(a,b,c,d,e)
f(a, b, c, d, e)
很多時候我們在編寫程式碼時會使用第二行這種方式,也就是每個逗號後面再加一個空格(當然並不是每個人都有這個習慣)。如果你也有這個習慣,應該能夠很容易地理解,這個問題簡單說就是英文逗號使用的空間小,作為分隔符不明顯,同時容易與成員操作符點號混淆。青語言中逗號也作為分隔符,其作用和空格相同,主要是為了從程式碼顯示上便於區分語法元素,那麼這個時候,中文逗號能夠更好地完成這個功能。
除此之外,與英文符號差別較大的應該就是中文的括號,包括【】和{}以及(),此外還有我們擴充套件的標籤型別使用的書名號《》。這些符號在顯示上通常相對於英文符號不夠圓潤(取決於使用的字型),但相較醒目,容易區分。這一點我們認為是符合青語言的設計要求的,尤其是面向青少年兒童時,比較醒目的符號能夠幫助他們更好地區分程式碼結構,提高程式碼可讀性。
當然,以上是我們目前在設計上的單方面的想法,後續我們還會根據使用者的反饋進行調整。
3、青語言關鍵字應該支援英文?
這一點完全可以做到,但是我們目前不計劃加入到語法實現中。因為如果你打算使用英文,那麼我們強烈建議你不要使用青語言,有更多成熟且優雅的程式語言供你選擇。而且,青語言在語法上參考JS,就是希望使用者能夠快速切換到JS或類似的語言。
以下是關於青語言語法設計的探討
目前青語言仍處於開發狀態,一些語法設計並未完全確定,以下是一些希望和大家一起探討的問題。
1、物件和程式碼塊
青語言參考JS,但我們發現JS的物件和程式碼塊在設計上都是通過大括號來表示,容易混淆。目前青語言採用了同樣的設計,這在教學中可能比較容易造成困惑。同時,由於青語言核心參考Lisp,我們保留了超程式設計能力(目前並不完整),所以執行時會出現程式碼塊型別,我們使用關鍵字‘元’來實現這個功能,例如:
元{……}
但這樣容易造成一些困擾,因為大括號在一些語句中直接標記為程式碼塊,作為資料的字面值時又表示物件,希望獲得程式碼塊型別的資料時又需要新增‘元’標記。
那麼這種情況下,可能需要對程式碼塊和物件進行更明確的區分。目前我們設想的一個方案是大括號直接表示程式碼塊,將物件的標記改為:
@{……}
也就是在大括號前多加一個@用作區分。另外,如果後期加上class的話,那麼類的構造方法就可以寫成:
@類名{}
因為@本身作為函數標記,從語法設計的角度看,能夠保持一致。
2、語境(作用域)的設計
首先,語境這個概念繼承自Lisp系的Rebol語言,並非青語言強行捏造(PS:Rebol是我非常喜歡的語言^-^)。
這個問題同樣是設計一致性的問題,Java中作用域與程式碼塊是一一對應的,但是JS中略有不同,if語句的大括號是不會建立作用域的。目前青語言是參考了JS的方式,這一點我們希望聽取大家的意見,確定應該採用哪一種方式。
3、陣列存取問題
前面提到的使用#和@作為變數和函數標記,但是目前還存在一個問題,也就是陣列中可以放任意型別的資料,然後通過序號(下標)來存取,那麼存取的時候可能不能夠確定該元素是變數還是函數。目前青語言對陣列元素的存取時比較寬鬆,可以用#和@存取任意型別的資料,沒有進行檢查。這一點我們也希望和大家一起探討,看有什麼方案可以改進。
以上是關於青語言語法設計的一些說明和探討的問題,其他可能存在的問題也歡迎大家一起探討。雖然我們預計本文同樣會收到較多差評,但還是希望能夠聽取不同的聲音,作為我們改進的方向。長久以來的程式設計習慣影響是非常深遠的,短時間內難以轉變,這一點我們完全理解,但開放與包容可能更利於我們認識世界。