下面这个紧张的例子,试图与我的真实情况相匹配,成功地完成了,但不是我想要的方式;我也不明白为什么,也无法在我的一本书中找到答案。
我可以看到,proc func是从全局级别调用的,然后最初被称为proc cofunc;也许,这就设置了upvar将使用的内容。但是proc finalize再次调用coroutine,并将变量名nbr传递给cofunc--后者调用add。在这方面,add“似乎”是finalize的两个级别。
upvar 2 $varName n in proc add是变量名nbr,它的值来自该名称的全局变量。我想从proc finalize (所以是15,而不是85)获得它,它似乎离proc add只有两个级别,但显然不在调用者上下文列表中。
我认为[yield]是原因;但是,请您解释一下为什么,更重要的是,如果proc finalize中的值不是一个数字,而是一个不应该传递的“大”值,那么是否可以从一个协同线中传递upvar或uplevel呢?
谢谢你考虑我的问题。
proc cofunc {callback vals} {
set var [yield]
$callback $vals $var
}
proc func {callback vals} {
set nbr 22
coroutine coro cofunc $callback $vals
}
proc add {vals varName} {
upvar 2 $varName n
chan puts stdout "varName: $varName; n: $n"
# => varName: nbr; n: 85
chan puts stdout [expr {[lindex $vals 0]+[lindex $vals 1]+$n}];
# => 115
}
proc finalize {nbr} {
coro nbr
}
set nbr 85
func add {10 20}
after 500 finalize 15
after 1000 set forever 1
vwait forever发布于 2022-07-24 11:19:02
upvar (像uplevel命令一样)是根据堆栈定义的。number参数表示堆栈上要执行多少步(或者可以在数字前面加上#以从另一端计数;这有点不常见);它默认为当前过程的调用方1。有两种堆栈框架,一种用于过程(以及相关实体,如方法和lambda表达式),另一种用于直接命名空间(全局范围、namespace eval和其他一些东西)。upvar所做的就是转到指定的堆栈框架,在那里查找指定的变量,并创建一个指向它的局部变量。所谓“链接”,我的意思是局部变量实际上是一个标记C指针,指向另一个变量的实现。一旦设置了链接变量,访问就非常快,因为访问的慢部分是将名称解析为实现,并且局部变量通常被编译成索引访问。
global和namespace upvar命令做一些非常相似的事情,但是使用不同的查找策略。(而且,global假定全局名称和本地名称应该匹配。)这也是variable命令的一部分。
在您的代码示例中,upvar 2将通过cofunc过程。如果是upvar #0,或者cofunc使用tailcall $callback,那么就可以使用简单的upvar了。我非常肯定,在add中访问的add与func中的不同,因为后者的堆栈框架届时将消失。
https://stackoverflow.com/questions/73095124
复制相似问题