2017-06-20 36 views
0

我想創建一個這樣簡單的例子程序:如何處理傳遞給PROC unexisting變量

proc name {args} { 
    foreach val $args { 
     puts $val 
    } 
} 

但我想處理不存在變量的過程,像碼事如下圖所示:

proc name {args} { 
    foreach val $args { 
     if [info exists $val] { 
      puts $val 
     } 
    } 
} 

的問題是,不執行代碼,因爲只要我調用過程與unexisting變量立即檔,進入代碼,說有那並不是一個變量之前不存在。這是否可能是因爲程序在進入身體之前檢查論證存在?

我可以通過使用預定義值更改args幾個可選變量來使其工作,但這會限制該過程並使其看起來很糟糕。

我可以創建一個處理未知變量的過程嗎?

回答

1

您無法傳遞變量作爲參數:參數必須是值。你可以作爲參數傳遞一個變量名稱並使用它作爲過程內的變量的引用。例如:

proc name args { 
    foreach varname $args { 
     upvar 1 $varname var 
     if {[info exists var]} { 
      puts $var 
     } 
    } 
} 

(至upvar調用建立,其名稱是程序外的可變varname和稱爲var的程序內的變量的值的變量之間的鏈路這是「傳遞變量單程。一個過程」)

然後,你可以這樣做:

% set foo 1 ; set baz 3 
% name foo bar baz 
1 
3 

請注意,如果你嘗試調用程序爲

% name $bar 

其中bar未定義,解釋器嘗試(並失敗)在調用過程之前對其進行評估。這可能是你所看到的。

文檔: upvar

0

您在這裏

if [info exists $val] 

犯了一個錯誤。當info exists使用應該對變量名,而不是變量值進行檢查。

讓我們來談談您的實際問題。

您可以將參數作爲鍵值對傳遞給過程,那麼它非常簡單。

proc user_info {args} { 
    #Converting the arguments into array 
    if {[catch {array set aArgs $args}]} { 
     puts "Please pass the arguments as key-value pair" 
     return 1 
    } 
    #Assume, we need to ensure these 3 arguments passed for sure. 
    set mandatoryArgs "-name -age -country" 
    foreach mArg $mandatoryArgs { 
     if {![info exists aArgs($mArg)]} { 
      puts "Missing mandatory argument '$mArg'" 
      return 1 
     } 
    } 
} 

user_info -name Dinesh 
1

如果我們看一下你在哪裏調用命令中的點(程序命令;他們是一個真正的子類),你會看到這樣的事情在你的代碼:

name $a $b $c 

那很好,如果存在的所有這些變量,但如果沒有,它就會炸燬name被稱爲甚至之前。在TCL,$a的意思是「讀變量a這裏使用它的內容」,不像其他一些語言,其中$的意思是「看的出來的語言,來了一個變量的名字!」

正因爲如此,我們需要改變調用約定是一個與這個工程:

name a b c 

那將需要使用upvar。像這樣:

proc name {args} { 
    foreach varName $args { 
     # Map the caller's named variable to the local name 「v」 
     upvar 1 $varName v 

     # Now we can work with v in a simple way 
     if {[info exists v]} { 
      puts $v 
     } 
    } 
}