coffeeak
coffeeak

Reputation: 3130

Cannot understand uplevel command in TCL

I am having some problems understanding the use of uplevel in TCL. I am reading Brent Welch's Practical programming in TCL and Tk and there is an example in uplevel that I cannot understand. Here it is:

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]
}

Can someone please explain it to me? The explanation in the book does not help me enough :(

Upvotes: 8

Views: 9272

Answers (2)

abcdefgh
abcdefgh

Reputation: 83

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"

here the most inside method a will be in level 0 and b in level ,c in level 2 and main program will be in level 3 so in proc a if i change the value of level then i can change the value of variable x of any proc be it a,b,c or main proc from method "a" itself. try changing level to 3,2,1,0 and see the magic putput.

Upvotes: 5

Donal Fellows
Donal Fellows

Reputation: 137597

The uplevel command executes a command (or in fact a script) in another scope than that of the current procedure. In particular, in this case it is uplevel 1 which means “execute in caller”. (You can also execute in the global scope with uplevel #0, or in other places too such as the caller's caller with uplevel 2 but that's really rare.)

Explaining the rest of that line: the use of the list here is as a way of constructing a substitution-free command, which consists of four words, foreach, the contents of the args variable, the contents of valueList variable, and break (which didn't actually need to be in braces). That will assign a value from the front of valueList to each variable listed in args, and then stop, and it will do so in the context of the caller.

Overall, the procedure works just like the built-in lassign in 8.5 (assuming a non-empty input list and variable list), except slower because of the complexity of swapping between scopes and things like that.

Upvotes: 8

Related Questions