Tcl Syntactic 之 const 和 tuple

Const 变量

proc const#check {name args} {
    return -code error -level 2 "const variable `\$$name` is readonly!"
}

proc const {name value} {
    upvar 1 $name var
    set var $value
    trace add variable var write [list tuple#check $name]
}

const abc 123    ;# 定义一个常量

set abc 456

Tuple

A tuple is a readonly list.

proc tuple#check {name args} {
    return -code error -level 2 "tuple `\$$name` is readonly!"
}

proc tuple {name value} {
    upvar 1 $name var
    set var $value
    trace add variable var write [list tuple#check $name]
}

tuple abc {1 2 3 4}   ;# 定义一个 tuple

set abc 456

#Error: tuple `$abc` is readonly!

利用 const 避免函数参数覆盖

下面的proc有一个参数name容易由于不小心被局部变量覆盖。

proc hello {name} {
  foreach {name} {a b c} {
     puts $name
  }
  puts "name = $name"
}

hello "tcler.net"

解决这个问题,一种方法是通过命名约定。比如 Vim Script 里面,参数变量通过 a:name的形式来访问——其中的a:表示参数。

另一种思路是让参数变量变成只读的。语义上类似于这样

proc const#alert {name} {
    return -code error -level 2 "argument `\$$name` is readonly!"
}

proc const {name} {
    upvar 1 $name var
    trace add variable var write [list const#alert $name]
}

proc hello {name} {
  const name

  foreach {name} {a b c} {
     puts $name
  }
  puts "name = $name"
}

让 trace 更简单

trace add variable $name write {
    return -code error "variable $name is readonly"
}
trace add variable $name write [lamda {name args} {
    return -code error "variable $name is readonly"
} $name]