Tcl 如何从全局空间中的proc访问列表

Tcl 如何从全局空间中的proc访问列表,tcl,Tcl,我需要列表在进程之外进行进一步处理。但是put$LIST显示一条错误消息没有这样的变量 我还尝试了upvar 0#LIST LIST而不是global,结果相同 我怀疑,麻烦制造者正在使用“list…”调用proc…如果我在调用proc时使用“list”,则命令global会执行它应该执行的操作, 但当然,代码作为一个整体不再正常工作 proc receiver {chan} { global LIST set data [gets $chan] set LIST [sp

我需要
列表
在进程之外进行进一步处理。但是
put$LIST
显示一条错误消息
没有这样的变量

我还尝试了
upvar 0#LIST LIST
而不是
global
,结果相同

我怀疑,麻烦制造者正在使用“list…”调用proc…如果我在调用proc时使用“list”,则命令
global
会执行它应该执行的操作, 但当然,代码作为一个整体不再正常工作

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]

如何在proc之外的全局空间中访问
LIST

我认为您必须在根命名空间中将
LIST
声明为全局:

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]

问题部分在于调用
put
命令时变量尚未写入,部分原因是您实际上不习惯异步工作

在打印变量之前,您需要等待某个变量到达。
vwait
命令非常适合(因为它在等待时运行Tcl事件循环)。我们可以告诉它等待(全局)
LIST
变量写入:当它被写入时,我们可以安全地读取它

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
这几乎可以,但是通过串行端口传入的变量是 每秒钟更新一次

如果这是要求,则:

(1) 在回调过程中打印从通道返回的值:
receiver

(2) 只需输入一次事件循环,不绑定到全局变量
List

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 ..."
这将进入一个事件循环,该循环绑定到一个未定义的变量
forever
,而不是从脚本中设置。因此,除非停止可执行文件(例如
tclsh
),或者不提供显式结束条件,否则它不会退出,例如:

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

谢谢你,Mathieu。不幸的是,这没有帮助。仍然是相同的错误消息。谢谢Donal Fellows。这几乎没问题,但通过串行端口传入的变量每秒都会更新,进程内的列表也会更新。但是对于vwait命令,进程外的列表只会第一次显示,然后再也不会显示。@Hans,为什么不打印出来呢e值从
receiver
proc本身的通道返回,不需要全局变量?我觉得这很自然:
proc receiver{chan}{set data[get$chan];put[split$data”,“]}
?@Hans问题的核心是,你有一个数据流通过串行线缓慢地进入,你必须决定何时采取行动以及采取什么行动。一旦你解决了这个问题,你需要编写的程序自然会跟进。thx,我不明白,我在全局空间中的何处可以找到这个列表。什么意思“从事件循环中退出…”确切地说?请你解释得更具体一点好吗?我想,我应该说得更清楚一点。我使用的
put
仅用于测试目的(显示在控制台中)。最后,我想在一个小部件中显示变量。我的意图是:首先创建一个列表,去掉
数据中的花括号。第二,将此列表放在全局命名空间中。第三,使用
lassign
将列表中的每个元素分配给一个变量。第四,将这些变量放入小部件中。要实现后者,我认为变量必须在全局名称空间中。这与您在中提出的问题(并得到了回答)有何不同?这仍然是相同的问题。上次我没有让它运行,因为我没有得到1)一个合适的列表和2)范围问题。然后我就忙着把它放在一边。同时,我修改了发送变量的发送器,这样我现在就可以得到一个包含实际代码的正确列表。但正如我在上一次评论中试图解释的那样,仍然存在范围问题。或者我错过了什么?首先,继续写你以前的文章会更好,IMO。其次,你试过运行建议给你的代码吗?上述代码片段中没有“范围问题”。我的建议是:运行脚本,如果失败,请让它运行(也可以联系我们)。然后,逐步浏览脚本以了解细节。