首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个upvar引用全局上下文?或者upvar可以用在协同线中吗?

为什么这个upvar引用全局上下文?或者upvar可以用在协同线中吗?
EN

Stack Overflow用户
提问于 2022-07-24 00:56:05
回答 1查看 52关注 0票数 0

下面这个紧张的例子,试图与我的真实情况相匹配,成功地完成了,但不是我想要的方式;我也不明白为什么,也无法在我的一本书中找到答案。

我可以看到,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中的值不是一个数字,而是一个不应该传递的“大”值,那么是否可以从一个协同线中传递upvaruplevel呢?

谢谢你考虑我的问题。

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-24 11:19:02

upvar (像uplevel命令一样)是根据堆栈定义的。number参数表示堆栈上要执行多少步(或者可以在数字前面加上#以从另一端计数;这有点不常见);它默认为当前过程的调用方1。有两种堆栈框架,一种用于过程(以及相关实体,如方法和lambda表达式),另一种用于直接命名空间(全局范围、namespace eval和其他一些东西)。upvar所做的就是转到指定的堆栈框架,在那里查找指定的变量,并创建一个指向它的局部变量。所谓“链接”,我的意思是局部变量实际上是一个标记C指针,指向另一个变量的实现。一旦设置了链接变量,访问就非常快,因为访问的慢部分是将名称解析为实现,并且局部变量通常被编译成索引访问。

globalnamespace upvar命令做一些非常相似的事情,但是使用不同的查找策略。(而且,global假定全局名称和本地名称应该匹配。)这也是variable命令的一部分。

在您的代码示例中,upvar 2将通过cofunc过程。如果是upvar #0,或者cofunc使用tailcall $callback,那么就可以使用简单的upvar了。我非常肯定,在add中访问的addfunc中的不同,因为后者的堆栈框架届时将消失。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73095124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档