2013-04-15 150 views
2

這裏是我的測試代碼:使用與TCL eval命令「設置」

proc check_eval {} { 
    set cmd {set return_val {}; set return_val} 
    puts "Command to evaluate : $cmd" 
    uplevel eval $cmd 
} 

我遇到了以下問題:當我打電話「check_eval」,它看起來像設置RETURN_VAL聲明」 {} 「被忽略。即,interpeter在調用範圍內查找現有的return_val變量。 實施例:

tcl>unset return_val 
tcl>check_eval 
Command to evaluate : set return_val {}; set return_val 
can't read "return_val": no such variable 
while evaluating check_eval 


tcl>set return_val 556 
556 
tcl>check_eval 
Command to evaluate : set return_val {}; set return_val 
556 
tcl> 

在另一方面,如果我替換 「設置RETURN_VAL {}」 中通過,例如, 「設置RETURN_VAL 10000」 的程序,它會運行時,顯示10000:

tcl>set return_val 556 
556 
tcl>check_eval 
Command to evaluate : set return_val 10000; set return_val 
10000 
tcl>set return_val 
10000 

有沒有人可以解釋我請這裏發生了什麼?

謝謝。

回答

4

您正在做兩個級別的評估/解釋,首先是uplevel,然後是eval,圍繞cmd腳本的大括號分組只能保護您不受第一個的影響。

你不需要eval,這樣就足夠了:

uplevel $cmd 

編輯:兩個evaluplevelconcat:enate所有的參數彙集成扁帶,並評估其作爲腳本(與uplevel你可以選擇另一個堆棧幀來運行它)。他們不使用第一個參數作爲單一命令名稱,而將其餘參數作爲發送到該命令的參數。如果是這種情況,您會收到eval的錯誤消息:找不到命令「set return_val {}; set return_val」。所以你正確使用eval,但是uplevel錯誤。

uplevel運行此腳本...

eval set return_val {}; set return_val 

...這在很多方面打破了,因爲你沒有列出報價(組),它的參數。

不需要你的榜樣eval,但你應該需要調用一個命令uplevel,沒有它的論點得到串聯,引用靜態字符串時,你不需要任何換人的方式,是用大括號:

uplevel {after 1000 {set return_val {}; set return_val}} 

...和引用動態字符串與它取代的值的方式,是具有list

set cmd {set return_val {}; set return_val} 
uplevel [list after 1000 $cmd] 
+0

@mkostya,讀出的[ 「評估和報價」](HTTP:// beedub .com/book/3rd/Eval.pdf)一書,以便更好地理解本書引用問題。 – kostix

+1

或者,'uplevel [list eval $ cmd]'。這與'uplevel $ cmd'完全相同,所以猜猜哪個更好... –

+0

感謝所有人(特別是potrzebie)的答案! – mkostya