Hans
Hans

Reputation: 11

How to access a list from proc in global space

I need LIST outside of proc for further procession. But puts $LIST shows an error message no such variable.

I have also tried upvar 0# LIST LIST instead of global with the same result.

I suspect, the troublemaker is calling proc with "list ..... If I ommit "list" in calling proc, the command global does what it should, but of course the code as a whole isn't working properly anymore.

proc receiver {chan} {
    global LIST
    set data [gets $chan]
    set LIST [split $data ,]  
}

puts $LIST  

set chan [open com5 r]
fconfigure $chan -mode "9600,n,8,1" -blocking 1 -buffering none -translation binary
fileevent $chan readable [list receiver $chan]

How can I get access to LIST in the global space outside of proc?

Upvotes: 1

Views: 430

Answers (3)

mrcalvin
mrcalvin

Reputation: 3434

It's almost ok but the variables incoming over the serial port are updated every second

If that is the requirement, then:

(1) Have the value returned from the channel be printed in the callback proc: receiver

(2) Enter the event loop just once, w/o binding to a global variable List or the like.

proc receiver {chan} {
    set data [gets $chan]
    puts [split $data ","]; # (1) print the return value
}

set chan [open com5 r]
fconfigure $chan -mode "9600,n,8,1" -blocking 1 -buffering none -translation binary
fileevent $chan readable [list receiver $chan]

vwait forever
puts "Quitted from event loop ..."

This will enter into an event loop that is bound to an undefined variable forever, not set from within your script. So it will not quit unless you stop the executable (e.g., tclsh) or unless you do not provide for an explicit ending condition, e.g.:

proc receiver {chan} {
    global counter
    set data [gets $chan]
    puts [split $data ","]; # (1) print the return value
    if {[incr counter] == 5} {
        global forever
        set forever 1; # (2) Exit the event loop, after receiver having been called 5 times
    }
}

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137567

The problem is partially that the variable hasn't been written at all yet when the puts command is called, and partially that you are not actually used to working asynchronously.

You need to wait for something to arrive before you can print the variable out. The vwait command is ideal for this (as it runs the Tcl event loop while waiting). We can tell it to wait for the (global) LIST variable to be written to: when it has been, we can safely read it.

proc receiver {chan} {
    global LIST
    set data [gets $chan]
    set LIST [split $data ","]  
}

set chan [open com5 r]
fconfigure $chan -mode "9600,n,8,1" -blocking 1 -buffering none -translation binary
fileevent $chan readable [list receiver $chan]

vwait LIST
puts $LIST

Upvotes: 1

Mathieu
Mathieu

Reputation: 9629

I think you must declare LIST as global in root namespace:

proc receiver {chan} {
    global LIST
    set data [gets $chan]
    set LIST [split $data ,]  
}

global LIST
puts $LIST  

set chan [open com5 r]
fconfigure $chan -mode "9600,n,8,1" -blocking 1 -buffering none -translation binary
fileevent $chan readable [list receiver $chan]

Upvotes: 0

Related Questions