f



Unable to understand "uplevel" and "upvar" in TCL

Hi,

I have never been able to understand "uplevel" and "upvar" in TCL and
when to use them?

Can anyone explain this to me in a way that I can understand, with
examples please?

Thanks,
Ahmed
0
Ahmed
12/21/2010 12:17:08 AM
comp.lang.tcl 23429 articles. 2 followers. Post Follow

4 Replies
1558 Views

Similar Articles

[PageSpeed] 19

Ahmed Omara wrote:

> Hi,
> 
> I have never been able to understand "uplevel" and "upvar" in TCL and
> when to use them?
> 
> Can anyone explain this to me in a way that I can understand, with
> examples please?

They are highly useful when implementing your own control structures, but 
it's not limited to. They make many tricky hacks possible.

Example for "uplevel" usage:

Let's say you want to implement procedure "fec" which means "for every 
character", which syntax is:

fec varName string code

Then you define:

###########################
proc fec {varName string code} {
  uplevel [list \
    foreach $varName \[split $string {}] {
      eval $code
    }
  ]
}
###########################

I don't know if this code works - I just wrote it here to present usage of 
"uplevel".
The whole "foreach" loop will be executed on upper level of stack, so if you 
execute:

set var1 "x"
fec v "abc" {puts "$var1, $v"}

then the code of "fec"'s body will resolve $var1 as it should, because that 
whole body code is executed at the same stack level as: set var1 "x"


Now example for "upvar" usage:

The "upvar" is somehow similar to "passing value by reference" in C++. 
Commands like "lappend" would use it if they were not implemented in C (in 
Tcl core). Here's a pseudo-code for "lappend" implemented in Tcl:

proc lappend {varName args} {
  upvar $varName var

  if {![info exists var]} {
    set var [list]
  }

  foreach arg $args {
    if {[llength $var] == 0} {
      set var [list $arg]
    } else {
      set var [concat $var [list $arg]]
    }
  }
}

See? We make a "link" with upper variable named as passed in $varName to 
local variable named "var", so we can use "var" variable locally as usual 
and then any changes made to "var" are also made to variable named as value 
of $varName on upper level of execution stack:

-- 
Pozdrawiam! (Regards!)
Googie
0
Googie
12/21/2010 7:45:09 AM
On Dec 21, 7:45=A0am, Googie <n...@spam.0rg> wrote:
> I don't know if this code works - I just wrote it here to present usage o=
f
> "uplevel".

Try this version which does work:

  proc fec {varName string body} {
     uplevel 1 [list foreach [list $varName] [split $string {}] $body]
  }

I prefer a longer example of [uplevel] (and [upvar] too):

  proc foreachline {varName fileName body} {
     upvar 1 $varName line
     set f [open $fileName]
     while {[gets $f line] >=3D 0} {
        uplevel 1 $body
     }
     close $f
  }

That makes it easy to process lines from a file, one at a time. It
even supports the control constructs [break] and [continue]; Tcl
really is that easy. Example of usage:

  # Simple (incomplete) INI parser
  foreachline l foo.ini {
     # Comment
     if {[string match ";*" $l]} {
        continue
     }
     # Section
     if {[regexp {^\[(.*)\]$} $l -> topic]} {
        set section $topic
     }
     # Property
     if {[regexp {^(\w+)=3D(.*)} $l -> name value]} {
        dict set properties($section) $name $value
     }
  }

> The "upvar" is somehow similar to "passing value by reference" in C++.

Here's how to do the [global] command in pure Tcl:

  proc global args {
     foreach var $args {
        uplevel 1 [list upvar #0 $var $var]
     }
  }

The other thing to note about [upvar] is that it creates very
efficient connections between local variables and the other variables.
(So too does [global] and [variable].)

Donal.
0
Donal
12/21/2010 8:17:27 AM
> Can anyone explain this to me in a way that I can understand, with
> examples please?

Doing so for sure requires understanding what you understand...

Do you understand 'scope', and if so, what languages are you familiar
with it in? (and if not, what languages are you familiar with?)
0
Neil
12/21/2010 4:51:22 PM
On Dec 20, 7:17=A0pm, Ahmed Omara <ahmad.abdulgh...@gmail.com> wrote:
> Hi,
>
> I have never been able to understand "uplevel" and "upvar" in TCL and
> when to use them?
>
> Can anyone explain this to me in a way that I can understand, with
> examples please?

I am going to quote liberally from "Tcl and the Tk Toolkit, 2nd ed.",
pg. 149, as to upvar:

"The upvar command provides a general mechanism for accessing
variables outside the context of a procedure....If 'a' is an array,
you cannot pass it to a procedure ... because there is no value for an
array as a whole; there are values only for the individual elements.
Instead you can pass the name of the array to the procedure ... and
use the upvar command to access the array's elements from the
procedure."

"Here is a simple example...."

proc printArray {name} {
    upvar $name a
    foreach el [lsort [array names a]] {
        puts "$el =3D $a($el)"
    }
}

set info(age) 37
set info(position) "Vice President"

printArray info

output:
"age =3D 37"
"position =3D Vice President"


Hope this helps
0
jemptymethod
12/22/2010 1:47:12 AM
Reply: