我的意思是为什么我们不能只使用已收到的变量作为过程中的参数。
你可以。它只是变得烦人。
通常,当您将变量的名称传递给命令时,命令可以修改该变量。典型的例子是set
andincr
命令,这两个命令都将变量的名称作为它们的第一个参数。
set thisVariable $thisValue
您也可以对过程执行此操作,但是当该变量是在过程调用者的上下文中定义的变量时,您需要从过程的上下文访问该变量,该变量可能是命名空间,也可能是不同的局部变量框架。为此,我们通常使用upvar
,它使局部变量的别名成为另一个上下文中的变量。
例如,这里是 的重新实现incr
:
proc myIncr {variable {increment 1}} {
upvar 1 $variable v
set v [expr {$v + $increment}]
}
为什么写入局部变量v
会导致调用者上下文中的变量被更新?因为我们给它起了别名(在内部,它是通过一个指向另一个变量的存储结构的指针来设置的;一旦upvar
完成它就会非常快)。global
和使用相同的底层机制variable
;它们都归结为快速变量别名。
你可以不这样做,只要你使用它uplevel
,但这会变得更烦人:
proc myIncr {variable {increment 1}} {
set v [uplevel 1 [list set $variable]]
set v [expr {$v + $increment}]
uplevel 1 [list set $variable $v]
}
这太恶心了!
或者,假设我们根本没有这样做。然后我们需要通过它的值传递变量,然后分配结果:
proc myIncr {v {increment 1}} {
set v [expr {$v + $increment}]
return $v
}
# Called like this
set foo [myIncr $foo]
有时是正确的,但工作方式完全不同!
Tcl 的核心原则之一是,您可以使用标准库命令(例如if
orputs
或incr
)执行的几乎所有操作也可以使用您自己编写的命令来完成。没有关键字。自然可能存在一些效率问题,并且某些命令可能需要用另一种语言(例如 C)完成才能正常工作,但语义不会使任何命令特别。它们都只是简单的命令。