我正在努力思考为什么我的下面带有第一个条件语句中的return
的代码会干净地退出,但是当我使用break
时出现错误invoked "break" outside of a loop
。有人可以向我解释吗?我的理解是break
将退出条件,而return
将仅返回一个值,然后退出到主体,并且Tcl解释器将继续评估代码。我的愿望是,如果arg1小于arg2则退出代码,而不评估剩余的arg3语句。我以为我可以用第一个代码块来做到这一点。但是,令我惊讶的是,第二个代码块这样做了却没有继续评估arg3。
这段带有break
的代码给了我上述错误:
proc myfunction {arg1 arg2} {
if {$arg1 < $arg2} {
puts "$arg1 too low"
break
} elseif {$arg1 >= $arg2} {
puts "Cool beans!"
}
set arg3 [expr {$arg1 + $arg2}]
return $arg3
}
带有return
的代码完全退出:
proc myfunction {arg1 arg2} {
if {$arg1 < $arg2} {
return [puts "$arg1 too low"]
} elseif {$arg1 >= $arg2} {
puts "Cool beans!"
}
set arg3 [expr {$arg1 + $arg2}]
return $arg3
}
答案 0 :(得分:1)
break
和return
都生成特殊的内部异常类型。然后,它们从生成它们的地方流到处理它们的东西,(在此讨论中)是过程外壳(制造堆栈框架,将实际参数映射到形式参数并在调用后整理)的东西。像for
或while
这样的循环结构。
当return
击中过程外壳时,它将转换为过程的正常结果,而其有效载荷值就是过程的结果。传统上,循环会忽略return
并让其循环(从技术上讲,它们可能会进行一些内部清理,尤其是使用foreach
时,但您看不到)。您可以传递其他选项以使return
有效负载执行其他操作,但是在这里它们并不重要。
break
遇到循环时,它将终止循环。当它碰到过程包时,它会转换为错误,您已经看到了错误,表明过程中存在一个break
百搭,这通常表示代码有误。
其他主要的异常处理类与catch
和try
以及用于处理所有异常的顶级处理程序相关。
还有另外两个主要的异常类别:error
,这是所有错误的所在,并包含诸如堆栈跟踪之类的附加信息;以及continue
,它使循环构造继续到下一个迭代。
Tcl的字节码编译器试图将break
和continue
异常转换为内部跳转,以消除对正确下一阶段处理的使用,从而消除它们的大多数使用。它并不是100%成功的,但是与非疯狂的代码甚至是相当疯狂的代码都非常接近。它还消除了return
最常见的情况。