如何处理传递给 proc 的不存在的变量
How to handle unexisting variables passed to a proc
我想创建一个类似这个简单示例的过程:
proc name {args} {
foreach val $args {
puts $val
}
}
但我希望过程能够处理不存在的变量,类似于下面显示的代码:
proc name {args} {
foreach val $args {
if [info exists $val] {
puts $val
}
}
}
问题是代码没有执行,因为一旦我用一个不存在的变量调用过程,它就会立即停止,在进入代码之前,说有一个不存在的变量。是否可能是因为程序在进入正文之前检查参数是否存在?
我可以通过用几个具有预定义值的可选变量更改 args
来使其工作,但这限制了程序并使其看起来很糟糕。
我可以让一个过程能够处理不存在的变量吗?
你在这里犯了一个错误
if [info exists $val]
当使用 info exists
时 它应该根据变量名而不是变量值进行检查。
让我们来谈谈您的实际问题。
您可以将参数作为键值对传递给过程,那就很简单了。
proc user_info {args} {
#Converting the arguments into array
if {[catch {array set aArgs $args}]} {
puts "Please pass the arguments as key-value pair"
return 1
}
#Assume, we need to ensure these 3 arguments passed for sure.
set mandatoryArgs "-name -age -country"
foreach mArg $mandatoryArgs {
if {![info exists aArgs($mArg)]} {
puts "Missing mandatory argument '$mArg'"
return 1
}
}
}
user_info -name Dinesh
您不能将变量作为参数传递:参数必须是值。您 可以 将变量 name 作为参数传递,并将其用作过程中变量的引用。示例:
proc name args {
foreach varname $args {
upvar 1 $varname var
if {[info exists var]} {
puts $var
}
}
}
(对 upvar
的调用在其名称为过程外部变量 varname
的值的变量和内部名为 var
的变量之间创建了一个 link程序。这是 "pass a variable to a procedure" 的一种方法。)
那么你可以这样做:
% set foo 1 ; set baz 3
% name foo bar baz
1
3
请注意,如果您尝试将过程调用为
% name $bar
其中 bar
未定义,解释器在调用过程之前尝试(但失败)对其求值。那可能就是你所看到的。
文档:
upvar
如果我们看一下你调用命令的地方(过程是命令;它们实际上是一个子类)你在您的代码中会看到类似这样的内容:
name $a $b $c
如果所有这些变量都存在,那很好,但如果一个不存在,它 将 甚至在调用 name
之前就崩溃了。在 Tcl 中,$a
的意思就是“读取变量 a
并在此处使用它的内容”,不像在其他一些语言中 $
的意思是“注意语言,这里有一个变量名!”
因此,我们需要将调用约定更改为适用于此的调用约定:
name a b c
这将需要使用 upvar
。像这样:
proc name {args} {
foreach varName $args {
# Map the caller's named variable to the local name “v”
upvar 1 $varName v
# Now we can work with v in a simple way
if {[info exists v]} {
puts $v
}
}
}
我想创建一个类似这个简单示例的过程:
proc name {args} {
foreach val $args {
puts $val
}
}
但我希望过程能够处理不存在的变量,类似于下面显示的代码:
proc name {args} {
foreach val $args {
if [info exists $val] {
puts $val
}
}
}
问题是代码没有执行,因为一旦我用一个不存在的变量调用过程,它就会立即停止,在进入代码之前,说有一个不存在的变量。是否可能是因为程序在进入正文之前检查参数是否存在?
我可以通过用几个具有预定义值的可选变量更改 args
来使其工作,但这限制了程序并使其看起来很糟糕。
我可以让一个过程能够处理不存在的变量吗?
你在这里犯了一个错误
if [info exists $val]
当使用 info exists
时 它应该根据变量名而不是变量值进行检查。
让我们来谈谈您的实际问题。
您可以将参数作为键值对传递给过程,那就很简单了。
proc user_info {args} {
#Converting the arguments into array
if {[catch {array set aArgs $args}]} {
puts "Please pass the arguments as key-value pair"
return 1
}
#Assume, we need to ensure these 3 arguments passed for sure.
set mandatoryArgs "-name -age -country"
foreach mArg $mandatoryArgs {
if {![info exists aArgs($mArg)]} {
puts "Missing mandatory argument '$mArg'"
return 1
}
}
}
user_info -name Dinesh
您不能将变量作为参数传递:参数必须是值。您 可以 将变量 name 作为参数传递,并将其用作过程中变量的引用。示例:
proc name args {
foreach varname $args {
upvar 1 $varname var
if {[info exists var]} {
puts $var
}
}
}
(对 upvar
的调用在其名称为过程外部变量 varname
的值的变量和内部名为 var
的变量之间创建了一个 link程序。这是 "pass a variable to a procedure" 的一种方法。)
那么你可以这样做:
% set foo 1 ; set baz 3
% name foo bar baz
1
3
请注意,如果您尝试将过程调用为
% name $bar
其中 bar
未定义,解释器在调用过程之前尝试(但失败)对其求值。那可能就是你所看到的。
文档: upvar
如果我们看一下你调用命令的地方(过程是命令;它们实际上是一个子类)你在您的代码中会看到类似这样的内容:
name $a $b $c
如果所有这些变量都存在,那很好,但如果一个不存在,它 将 甚至在调用 name
之前就崩溃了。在 Tcl 中,$a
的意思就是“读取变量 a
并在此处使用它的内容”,不像在其他一些语言中 $
的意思是“注意语言,这里有一个变量名!”
因此,我们需要将调用约定更改为适用于此的调用约定:
name a b c
这将需要使用 upvar
。像这样:
proc name {args} {
foreach varName $args {
# Map the caller's named variable to the local name “v”
upvar 1 $varName v
# Now we can work with v in a simple way
if {[info exists v]} {
puts $v
}
}
}