Stored procedures 如何处理传递给proc的不存在的变量

Stored procedures 如何处理传递给proc的不存在的变量,stored-procedures,tcl,args,Stored Procedures,Tcl,Args,我想创建一个类似以下简单示例的过程: proc name {args} { foreach val $args { puts $val } } 但是我希望这个过程能够处理不存在的变量,比如下面的代码: proc name {args} { foreach val $args { if [info exists $val] { puts $val } } } 问题是代码没有被执行,因为只

我想创建一个类似以下简单示例的过程:

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]
信息存在时
被使用应根据变量名称而不是变量值进行检查。

让我们来谈谈你的实际问题

您可以将参数作为键值对传递给过程,这非常简单

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

你犯了个错误

if [info exists $val]
信息存在时
被使用应根据变量名称而不是变量值进行检查。

让我们来谈谈你的实际问题

您可以将参数作为键值对传递给过程,这非常简单

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

不能将变量作为参数传递:参数必须是值。可以将变量名作为参数传递,并将其用作过程中变量的引用。例如:

proc name args {
    foreach varname $args {
        upvar 1 $varname var
        if {[info exists var]} {
            puts $var
        }
    }
}
(对
upvar
的调用在过程外部变量
varname
的值与过程内部变量
var
之间创建链接。这是“将变量传递给过程”的一种方法。)

然后你可以这样做:

% set foo 1 ; set baz 3
% name foo bar baz
1
3
请注意,如果您尝试按以下方式调用该过程:

% name $bar
如果
bar
未定义,解释器会在调用过程之前尝试(但失败)对其求值。这可能就是你所看到的

文件:
不能将变量作为参数传递:参数必须是值。可以将变量名作为参数传递,并将其用作过程中变量的引用。例如:

proc name args {
    foreach varname $args {
        upvar 1 $varname var
        if {[info exists var]} {
            puts $var
        }
    }
}
(对
upvar
的调用在过程外部变量
varname
的值与过程内部变量
var
之间创建链接。这是“将变量传递给过程”的一种方法。)

然后你可以这样做:

% set foo 1 ; set baz 3
% name foo bar baz
1
3
请注意,如果您尝试按以下方式调用该过程:

% name $bar
如果
bar
未定义,解释器会在调用过程之前尝试(但失败)对其求值。这可能就是你所看到的

文件:

如果我们看一下您调用命令的位置(过程是命令;它们实际上是一个子类),您将在代码中看到如下内容:

name$a$b$c
如果所有这些变量都存在,这很好,但如果不存在,它将在调用
name
之前爆炸。在Tcl中,
$a
的意思正是“读取变量
a
并在此处使用其内容”,而在其他一些语言中,
$
的意思是“注意语言,这里有一个变量名!”

因此,我们需要将调用约定更改为适用于以下内容的约定:

name a b c
这需要使用
upvar
。像这样:

proc name{args}{
foreach varName$args{
#将调用方的命名变量映射到本地名称“v”
upvar 1$varName v
#现在我们可以用一种简单的方法来处理v
如果{[info exists v]}{
卖出$v
}
}
}

如果我们看一下您调用命令的位置(过程是命令;它们实际上是一个子类),您将在代码中看到如下内容:

name$a$b$c
如果所有这些变量都存在,这很好,但如果不存在,它将在调用
name
之前爆炸。在Tcl中,
$a
的意思正是“读取变量
a
并在此处使用其内容”,而在其他一些语言中,
$
的意思是“注意语言,这里有一个变量名!”

因此,我们需要将调用约定更改为适用于以下内容的约定:

name a b c
这需要使用
upvar
。像这样:

proc name{args}{
foreach varName$args{
#将调用方的命名变量映射到本地名称“v”
upvar 1$varName v
#现在我们可以用一种简单的方法来处理v
如果{[info exists v]}{
卖出$v
}
}
}