Tcl `阵列nextelement`--can';当searchId无效时,无法捕获错误

Tcl `阵列nextelement`--can';当searchId无效时,无法捕获错误,tcl,Tcl,我已经并且正在做一个练习来实现数组foreach(是的,我知道) 我正在使用数组startsearch/more/nextelement/donesearch。我现在试图捕获在搜索过程中添加或删除数组元素时抛出的错误:我发现我无法在代码中捕获该错误,但我可以在交互式会话中捕获它 下面是一个互动会话: % array set Y {foo bar baz qux} % set sid [array startsearch Y] s-1-Y % set key [array nextelement

我已经并且正在做一个练习来实现
数组foreach
(是的,我知道)

我正在使用数组startsearch/more/nextelement/donesearch。我现在试图捕获在搜索过程中添加或删除数组元素时抛出的错误:我发现我无法在代码中捕获该错误,但我可以在交互式会话中捕获它

下面是一个互动会话:

% array set Y {foo bar baz qux}
% set sid [array startsearch Y]
s-1-Y
% set key [array nextelement Y $sid]
foo
% set Y(hello) world
world
% try {
  set key [array nextelement Y $sid]
} trap {TCL LOOKUP} {msg e} {puts "$sid has been invalidated\n$e"}
s-1-Y has been invalidated
-code 1 -level 0 -errorstack {INNER {invokeStk1 ::tcl::array::nextelement Y s-1-Y}} -errorcode {TCL LOOKUP ARRAYSEARCH s-1-Y} -errorinfo {couldn't find search "s-1-Y"
    while executing
"array nextelement Y $sid"
    ("try" body line 1)} -errorline 1
% 
一切都好。我们可以看到,在我添加了一个数组元素之后,当一个活动搜索正在进行时,searchId无效:错误代码以
{TCL LOOKUP ARRAYSEARCH}

现在,我将其包装在一个proc中,并安排在启动交互式tclsh时对其进行源代码获取(有关详细信息,请参阅)。这是我的
数组foreach
过程的主体:

% info body ::monkeypatches::array_foreach

    if {[llength $vars] != 2} {
        error {array foreach: "vars" must be a 2 element list}
    }
    lassign $vars keyVar valueVar

    # Using the complicated `upvar 1 $arrayName $arrayName` so that any
    # error messages propagate up with the user's array name
    upvar 1 $arrayName $arrayName  $keyVar    key  $valueVar  value

    set sid [array startsearch $arrayName]
    while {[array anymore $arrayName $sid]} {
        # This doesn't seem to be able to catch the error when the user
        # tries to modify the array during a search. Hmm.
        try {
            set key [array nextelement $arrayName $sid]
        } trap {TCL LOOKUP ARRAYSEARCH} {"" e} {
            return -options $e "detected attempt to modify the array while iterating"
        }
        set value [set "${arrayName}($key)"]
        uplevel 1 $body
    }
    array donesearch $arrayName $sid
    return
当我重现捕捉错误的步骤时,我发现我的
try
没有捕捉到错误:

% array set Y {foo bar baz qux}
% array foreach {key val} Y {set Y(hello) world}
couldn't find search "s-1-Y"
将特定的
trap
子句替换为通用的
on error
没有帮助。使用
catch
而不是
也不能尝试


我不明白为什么这个进程不能捕获错误。有什么想法吗?

如果您查看错误跟踪,您会发现错误并非来自您预期的地方。(为了本测试的目的,我创建了一个名为
array\u foreach
的过程。)

您已经在
阵列nextelement
上设置了陷阱,但不再在
阵列上设置陷阱,这是实际检测问题(并抛出问题)的地方

我想您最好将循环更改为:

while true {
    try {
        if {![array anymore $arrayName $sid]} {
            break
        }
        set key [array nextelement $arrayName $sid]
        set value [set ${arrayName}($key)]
    } trap {TCL LOOKUP ARRAYSEARCH} {"" e} {
        return -options $e "detected attempt to modify the array while iterating"
    }
    uplevel 1 $body
}

哦。谢谢你,多纳尔。
while true {
    try {
        if {![array anymore $arrayName $sid]} {
            break
        }
        set key [array nextelement $arrayName $sid]
        set value [set ${arrayName}($key)]
    } trap {TCL LOOKUP ARRAYSEARCH} {"" e} {
        return -options $e "detected attempt to modify the array while iterating"
    }
    uplevel 1 $body
}