upvar, pass by name

Tcl proc 參數是 pass by value 的:

proc printName {employeeName} {
    puts "employeeName = $employeeName"
}

set name "cooper maa"
printName $name

如你所預期的,上列這段 Script 的輸出是:

employeeName = cooper maa

假若你將 Script 改成這樣,結果會是一樣的:

proc printName {varName} {
    # 宣告一個區域變數 employeeName,employeeName 變數是上一層 的某個變數的分身
    upvar $varName employeeName
    
    puts "employeeName = $employeeName"
}

set name "cooper maa"
printName name

我們都知道,Tcl 是不必宣告變數的,要產生新變數,隨時 set 一下就行。upvar 是故意來「破壞規矩」的指令,它的目的就是宣告變數用的!

上列 Script 中:

 upvar $varName employeeName

這行指令是個倒裝句,它的意思是說「在 proc 內,宣告一個 employeeName 區域變數,而這個 emplyeeName 變數,其實是呼叫者那一層某個變數的分身」,可是到底 employeeName 是誰的分身呢?答案就存在 varName 變數裏,經由呼叫 printName 時傳遞過來的,也就是特別標示的那行:

printName name

name (Golobal Scope 的一個變數)會傳入 printName 並儲存在 varName 變數中。所以 $varName 就會得到 name,那 upvar 指令就可以為 Global Scope 的這個 name 變數做出一個分身,就管它叫 employeeName 囉!


相同的事不需要 upvar 也做得到,為什麼要用 upvar 呢?是這樣的,因為我們沒辦法以 pass by value 的方式傳遞 array,如果要把陣列傳給 proc 處理, 就會需要用到 upvar 指令。底下是傳遞 array 到 proc 的範例:

# 用來設定陣列的內容
proc
setEmployee {varName name age height weight} {
    upvar $varName employee
    
    set employee(name)   $name
    set employee(age)    $age
    set employee(height) $height
    set employee(weight) $weight
}

# 用來印出陣列的內容
proc printEmployee {varName} {
    upvar $varName employee
    
    puts "Employee info:"
    puts "Name   = $employee(name)"
    puts "Age    = $employee(age)"
    puts "Height = $employee(height)"
    puts "Weight = $employee(weight)"
}

# 陣列一開始是空的
array set anEmployee {}

# pass by name (anEmployee array)
setEmployee anEmployee coopermaa 28 167 65
printEmployee anEmployee

這段 Script 的輸出為:

Employee info:
Name   = coopermaa
Age    = 28
Height = 167
Weight = 65

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值