如何处理传递给 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
        }
    }
}