View · Search · Index
No registered users in community xowiki
in last 10 minutes

[Xotcl] Using uplevel within instprocs from instprocs

From: <MichaelL_at_frogware.com>
Date: Mon, 15 Nov 2004 17:16:40 -0500

I've defined a proc which is supposed to be a control structure that
iterates over the children of an object. There's a problem, though, when I
nest calls.

Here's some code:

    Object instproc each {objName body} {
        puts " *** level = [info level]"
        puts " *** self callinglevel = [self callinglevel]"
        uplevel [self callinglevel] [list foreach $objName [lsort [[self]
info children]] $body]
    }

    Class TestB

    Class TestA

    TestA instproc init {args} {
        next
        TestB [self]::b1
        TestB [self]::b2
        TestB [self]::b3
    }

    Class Test

    Test instproc init {args} {
        next
        TestA [self]::a1
        TestA [self]::a2
        TestA [self]::a3
    }

    Test instproc loop1 {} {
        set i 0
        [self] each a {
            incr i
            puts "$a"
        }
        puts "Total = $i"
    }

    Test instproc loop2 {} {
        set i 0
        [self] each a {
            incr i
            puts "$a"
            $a each b {
                incr i
                puts " $b"
            }
        }
        puts "Total = $i"
    }

    Test t

    t loop1
    t loop2

Here's some output:

 *** level = 2
 *** self callinglevel = #1
::t::a1
::t::a2
::t::a3
Total = 3
 *** level = 2
 *** self callinglevel = #1
::t::a1
 *** level = 2
 *** self callinglevel = #2
can't read "i": no such variable
    (reading value of variable to increment)
    invoked from within
"incr i"
    ("foreach" body line 2)
    invoked from within
"foreach b {::t::a1::b1 ::t::a1::b2 ::t::a1::b3} {
                incr i
                puts " $b"
            }"
    ("uplevel" body line 1)
    invoked from within
"uplevel [self callinglevel] [list foreach $objName [lsort [[self] info
children
]] $body]"
    (procedure "each" line 5)
    ::t::a1 ::xotcl::Object->each
    invoked from within
"$a each b {
                incr i
                puts " $b"
            }"
    ("foreach" body line 4)
    invoked from within
"foreach a {::t::a1 ::t::a2 ::t::a3} {
            incr i
            puts "$a"
            $a each b {
                incr i
                puts " ..."
    ("uplevel" body line 1)
    invoked from within
"uplevel [self callinglevel] [list foreach $objName [lsort [[self] info
children
]] $body]"
    (procedure "each" line 5)
    ::t ::xotcl::Object->each
    invoked from within
"[self] each a {
            incr i
            puts "$a"
            $a each b {
                incr i
                puts " $b"
            }
    ..."
    (procedure "loop2" line 4)
    ::t ::Test->loop2
    invoked from within
"t loop2"
    invoked from within
"if 1 {
    Object instproc each {objName body} {
        puts " *** level = [info level]"
        puts " *** self callinglevel = [self cal..."
    (file "XOTcl-test.tcl" line 7)

You can see that the one-level iterator succeeds, but the two-level
iterator can't see the variable defined in the outer loop. You can also
see that the first time "level" and "callinglevel" are different (as you
would expect) but the second time they're the same (which looks like it
might be an XOTcl bug). Any ideas?

(I can work around this for now, of course, but it would be nice to figure
out what's wrong.)