2011-04-29 74 views
1

我發現了非常奇怪的錯誤(?),它讓我幾乎整天都在實際應用中找到它。在代碼中有一個elseif塊被註釋掉,並導致執行代碼(我認爲)無法執行。if/else塊內的tcl註釋的奇怪行爲。這是tcl解釋器的錯誤嗎?

我簡化了測試用例,它重現了這種奇怪的tcl行爲。

proc funnyProc {value} { 
    if {$value} { 
    return "TRUE" 
# } elseif {[puts "COMMENT :)"] == ""} { 
# return "COMMENT" 
    } else { 
    return "FALSE" 
    } 
    return "IT'S IMPOSSIBLE!!!" 
} 

puts [funnyProc false] 

你認爲這個程序會輸出什麼?

  1. 註釋行中的puts被執行。從任何編程語言POV都不可能。
  2. if {...} {return} else {return}之後的行也被執行。從邏輯true/false是不可能的。

我知道tcl-comment的行爲類似於名稱爲#的命令,並且使用所有參數直到EOL。而tcl解析器不喜歡評論中的不平衡大括號。但是這個情況超出了我的理解。

也許我錯過了一些重要的東西?如何正確評論這樣的elseif塊,所以不要有這些奇怪的副作用?

+0

這太瘋狂了!我注意到,如果在「elseif」行末尾加上「{」,那麼代碼將按照預期行事。 – 2011-04-29 15:32:18

回答

6

這是因爲#僅僅是一個註釋時的Tcl正在尋找一個命令開始,並在第一時間就看到它上面(解析if時),它在尋找一個}以關閉較早{ 。這是Tcl解析規則的結果; if只是一個命令,而不是一個特殊的構造。

Ernest指出的效果是因爲它增加了該行上的大括號的嵌套級別,這使得它成爲從if {$value} {行末尾到} else {行末尾的參數的一部分。然後當if評估腳本時#變得特別。 (好吧,除了所有的字節碼被編譯,但這是一個實現細節:除了一些非常惡劣的邊緣情況外,觀察到的語義是相同的。)

+0

看來你是對的。如果在第一個'#'之後按Return鍵來分割第一條註釋行,則行爲不會改變。但現在顯然可以理解的是,有兩段代碼:空註釋行和未註釋的'elseif',其正文中只有註釋。謝謝。 PS。我正在使用的編輯器中的語法高亮無法正確處理這種情況,這是誤導。 – GrAnd 2011-04-29 17:08:08

+0

@GrAnd:再次強調:是的,它是已知的。 (所有?大多數?)熒光筆預期使用詞法分析器/分析器模型的後果,這不太適合Tcl。 – 2011-04-30 16:34:11

相關問題