首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在通道事件调用过程并检索指针指向的值时使用upvar?

在通道事件调用过程并检索指针指向的值时使用upvar?
EN

Stack Overflow用户
提问于 2021-07-26 04:17:37
回答 1查看 32关注 0票数 0

关于下面的代码,我有两个问题。

当通道事件调用

  1. 时,是否可以在ReadLine中使用upvar?在upvar的实验中,我使用了这个完全相同的场景,但ReadLine是直接而不是通过事件调用的;而且它运行得很好。它失败了,因为state($sock)是不被识别的。是否需要一个不同的#n值,还是必须是全局的?它尝试了#2,这引发了一个错误,这是一个坏值。

  1. In procedure ReadLine I试图创建指向$state($sock)的指针,使其指向列表本身。例如,在实验中,lappend $sptr $op运行得很好,但是在set row [lindex $sptr 0]上失败了,因为$sptrstate(1)。但是,如果使用set (如set row [lindex [set $sptr] 0] ),则确实有效。为什么会这样呢?是否有另一种方法来获取指针所指向的值?试图在Tcl中使用指针是个坏主意吗?将过程体转换为字节码表示的事实是否意味着使用指针没有多大区别?

谢谢。

代码语言:javascript
复制
proc ClientConnect {sock client_ip client_port} {    
   if {![info exists state($sock)]} {set state($sock) {1}}; 
   chan configure $sock -buffering line -blocking 0 -translation crlf
   chan event $sock readable [list ReadLine $sock]
}

proc ReadLine {sock} {

  # The #1 in upvar is to first caller, which is ClientConnect.
  # Make a ptr to the array list rather than retrieving it each reference,
  # such that $sptr is state($sock)'s list.

  upvar #1 state r
  set sptr r($sock)
  puts stdout "x: [lindex $r($sock) 0]"; #Fails to recognize state.
  set row [lindex [set $sptr] 0]
}

似乎工作正常的实验代码:

代码语言:javascript
复制
proc ReadLine {sock} {
 upvar #1 row rtemp; #Recognizes row.
 set r rtemp($sock)
 lappend $r "new"

 set line "Content-length: 247899"
 if { [string first "Content-length:" $line] == 0 } { lappend $r [string trim [string range $line 16 end]] }

 lappend $r "help"
 puts [lindex [set $r] 3]; #Output is: 247899.
 puts $rtemp($sock); #Output is: 1 GET new 247899 help.
}
    
proc do {sock} {
  set row($sock) {1 GET}
  ReadLine $sock
}

set sock 1
do $sock
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-26 14:21:39

如果需要,可以使用upvar,但是您会发现回调上面唯一可见的堆栈帧是全局堆栈框架。就好像它是用uplevel #0调用的。它看不到内部过程,如果您稍微考虑一下,原因是显而易见的:当调用发生时,不能保证堆栈上有任何特定的过程。

如果需要将状态从安装回调的位置传递到调用回调的位置,最简单的方法是使用协同(可以从实际的全局回调恢复)或使用TclOO对象(当然,可以封装各种复杂的状态)。在8.5和之前的版本中,您受到了更多的限制,必须使用全局/命名空间变量,这可能会变得更加混乱。

若要使变量访问正常工作,请使用upvar为变量创建别名:

代码语言:javascript
复制
# upvar 0 is special in that it aliases a currently-visible variable
upvar 0 row($sock) r
puts [lindex $r 0]

唯一真正的限制是不能在数组中放置数组。它在很久以前就被删除了,因为它很难使用,而且容易导致崩溃。

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

https://stackoverflow.com/questions/68524444

复制
相关文章

相似问题

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