首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >upvar的目的是什么?

upvar的目的是什么?
EN

Stack Overflow用户
提问于 2016-02-19 13:48:56
回答 3查看 1.2K关注 0票数 3

在我目前处理的TCL代码中,每个过程中的参数都被upvar编辑成一个局部变量,然后使用。

代码语言:javascript
复制
proc configure_XXXX { params_name_abc params_name_xyz} {
    upvar $params_name_abc abc
    upvar $params_name_xyz xyz
}

从现在起,abc和xyz将被用来做任何事情。我读了upvar TCL wiki,但不明白它的优点。我的意思是,为什么我们不能在这个过程中仅仅使用已经接收到的变量作为参数。谁能详细说明一下吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-19 15:44:06

我的意思是,为什么我们不能在这个过程中仅仅使用已经接收到的变量作为参数。

你可以的。只是有点烦人。

通常,当您将变量的名称传递给命令时,就是为了使命令能够修改该变量。典型的例子是setincr命令,它们都以变量的名称作为第一个参数。

代码语言:javascript
复制
set thisVariable $thisValue

您也可以使用过程来实现这一点,但是当变量是在过程调用方的上下文中定义的变量时,需要从过程上下文访问变量,该变量可能是一个名称空间,也可能是一个不同的局部变量框架。为此,我们通常使用upvar,它使别名从局部变量变为另一个上下文中的变量。

例如,下面是incr的重新实现

代码语言:javascript
复制
proc myIncr {variable {increment 1}} {
    upvar 1 $variable v
    set v [expr {$v + $increment}]
}

为什么写入局部变量v会导致调用方上下文中的变量被更新?因为我们已经对它进行了别名(在内部,它是通过指向另一个变量的存储结构的指针来设置的;一旦完成了upvar,它就会非常快)。globalvariable也使用同样的底层机制;它们都归结为快速变量别名。

如果您不使用uplevel,您可以不使用它,但这会变得更烦人:

代码语言:javascript
复制
proc myIncr {variable {increment 1}} {
    set v [uplevel 1 [list set $variable]]
    set v [expr {$v + $increment}]
    uplevel 1 [list set $variable $v]
}

太恶心了!

或者,假设我们根本没有这样做。然后,我们需要通过变量的值传递变量,然后将结果赋值:

代码语言:javascript
复制
proc myIncr {v {increment 1}} {
    set v [expr {$v + $increment}]
    return $v
}

# Called like this
set foo [myIncr $foo]

有时候是对的,但工作方式完全不同!

Tcl的核心原则之一是,使用标准库命令(例如ifputsincr)所能做的几乎任何事情都可以用您自己编写的命令来完成。没有关键词。当然,可能存在一些效率问题,有些命令可能需要用另一种语言(如C)来正确工作,但是语义并不会使任何命令变得特殊。他们都只是简单的命令。

票数 6
EN

Stack Overflow用户

发布于 2016-02-19 14:09:25

upvar命令将允许您修改块中的变量,并使修改后的从父块中可见。

试试这个:

代码语言:javascript
复制
# a function that will modify the variable passed
proc set_upvar { varname } {
    upvar 1 $varname var
    puts "var was $var\n"
    set var 5
    puts "var is now $var\n"
}

# a function that will use the variable but that will not change it
proc set_no_upvar { var } {
    puts "var was $var\n"
    set var 6
    puts "var is now $var\n"
}

set foo 10

# note the lack of '$' here
set_upvar foo
puts "foo is $foo\n"

set_no_upvar $foo
puts "foo is $foo\n"
票数 2
EN

Stack Overflow用户

发布于 2016-02-19 14:47:52

正如上面的注释所提到的,它经常用于通过引用传递函数参数(通过引用调用)。一幅画要花一千字:

代码语言:javascript
复制
proc f1 {x} {
    upvar $x value
    set value 0
}

proc f2 {x} {
    set x 0
}

set x 1
f1 x
puts $x

set x 1
f2 x
puts $x

将导致:

$./call by-参.call 0 1

使用upvar,我们将变量x更改为函数之外的变量(从1更改为0),而没有upvar,则没有。

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

https://stackoverflow.com/questions/35506914

复制
相关文章

相似问题

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