看了點groovy的ml archives,爭論不休的EOS/EOL問題。
C-style的語言本沒有EOS問題,文法規定顯式的';'作為EOS。但是從JavaScript這個異類開始,使用了Automatic Semicolon Insertion的方式,使得在許多情況下,';'是可省略的。
以前就看到有人詬病這種設計,現在才突然發現,其產生含混的根源是:其他不用';'的語言多以EOL作為天然的EOS,但是這種可省略';'的設計導致缺乏確定的EOS,有時候EOL是EOS,有時候又不是!依賴內容相關的判斷在某些情況下並不是很直觀。
這種情況在Groovy更嚴重。
Groovy有更抽象的設計原則叫做PHIM: "Parse how I mean"。以這種思想為指引,產生許多有趣同時又是危險的特性,例如可以省略return關鍵字。
更自由的文法似乎不可避免帶來更多歧義性,PHIM往往產生含混和衝突。權衡的結果是需要一些更嚴格的限制,例如有人建議是只有Method/Closure最後一行才能省略return關鍵字。
現在根據符合直覺和簡潔的目標,在ml的threads中,參與者不斷的提出和改進針對EOS問題的建議,我覺得比較能接受的意見是:非平衡的括弧、運算子(以及承襲java的少數keyword結構如if(...)、for(...)、else等)後的EOL不作為EOS。付出的代價是和Java/C等在如下語句意義上的不一致:
a = 1
+ 2
+ 3;
同時,與JavaScript也不一致:
a = f
(param)
類似的問題還有一些。比如最搞笑的一個comment問題:
a = 1 // comment
b = 2 // comment
+ 1 // comment
c = 3 /* comment
comment */ + 1
顯然在/*comment*/中,任何comment都被忽略,包括EOL。而在//comment文法中,按照java的規定最後的EOL也是comment的一部分被忽略,這沒問題,因為Java中EOS=';'。但是缺乏明確EOS的groovy是不能忽略EOL的,否則就會有奇怪的事情發生(第1、2行結果變成了 a=1b=2)。當然這主要是grammar上的issue,而不是實踐上的issue。
可以預見,EOS問題今後還會被不斷老調重彈,典型的句型是:“假如去掉optional semcolon的特性,這個文法上的issue就很容易解決……”
然而,儘管有很多證據顯示省略';'可能帶來了大量麻煩,但是John Wilson的話還是蠻有道理的:
No expert programmers *hate* the situation in which the compiler throws out the program because of a missing semicolon. They ask the very reasonable question "if the compiler knows there should be a semicolon there why the **** doesn't it put it in?"
因此我總體上還是贊同這個特性的。