无法理解TCL中的uplevel命令

无法理解TCL中的uplevel命令,tcl,Tcl,我在理解uplevel在TCL中的使用时遇到了一些问题。我正在阅读布伦特·韦尔奇(Brent Welch)在TCL和Tk中的实用编程,在uplevel中有一个我无法理解的例子。这是: proc lassign {valueList args} { if {[llength $args] == 0} { error "wrong # args:lassign list varname ?varname...?" } if {[llength $valueList] == 0}

我在理解uplevel在TCL中的使用时遇到了一些问题。我正在阅读布伦特·韦尔奇(Brent Welch)在TCL和Tk中的实用编程,在uplevel中有一个我无法理解的例子。这是:

proc lassign {valueList args} {
  if {[llength $args] == 0} {
    error "wrong # args:lassign list varname ?varname...?"
  }
  if {[llength $valueList] == 0} {
    #Ensure one trip through the foreach loop
    set valueList [List {}]
  }
  uplevel 1 [list foreach $args $valueList {break}]
  return [lrange $valueList [llength $args] end]
}

谁能给我解释一下吗?这本书中的解释对我的帮助还不够:(

uplevel命令在当前过程之外的另一个范围内执行命令(或者实际上是脚本)。特别是,在这种情况下,它是
uplevel 1
,意思是“在调用者中执行”。(您也可以使用
uplevel#0
在全局范围内执行,也可以使用
uplevel 2
在其他地方执行,例如调用方的调用方,但这种情况非常罕见。)

解释该行的其余部分:这里使用
list
是一种构造无替换命令的方法,该命令由四个字组成,
foreach
,变量
args
的内容,
valueList
变量的内容,以及
break
(实际上不需要放在大括号中)。这将从
valueList
的前面为
args
中列出的每个变量分配一个值,然后停止,并将在调用方的上下文中执行此操作

总的来说,该过程的工作原理与8.5中内置的
lassign
类似(假设输入列表和变量列表为非空),但由于在作用域和类似对象之间交换的复杂性,速度较慢

proc a {} {
  set x a
  uplevel 3 {set x Hi}
  puts "x in a = $x"
}
proc b {} {
  set x b
  a
  puts "x in b = $x"
}
proc c {} {
  set x c
  b
  puts "x in c = $x"
}
set x main
c
puts "x in main == $x"
在这里,最内部的方法a将在级别0中,b将在级别2中,c将在级别3中,因此在过程a中,如果我更改级别的值,那么我可以更改任何过程的变量x的值,无论是方法“a”本身的变量a、b、c还是主过程。
尝试将level更改为3,2,1,0,然后查看神奇的putput。

在8.6中,我们设法找到了
uplevel#1
与协同程序的用法。这被认为是该特定形式有史以来的第一次实际使用,尽管它已经合法了几十年。语法描述如下:“如果级别由#后跟一个数字组成,则该数字给出一个绝对级别数字。”@DonalFellows不
tailcall
顶部
coroutine
堆栈。