这goto
句话是我工作中的禁忌。
于是下面的问题就诞生了……
是否存在 agoto
是唯一有效解决方案的情况?
是否存在 a
GOTO
是唯一有效解决方案的情况?
我想这取决于你所说的有效。我想您是在问是否存在只能使用该goto
语句编写的程序。在这种情况下,答案是没有这样的程序。Delphi 是图灵完备的,不管有没有goto
声明。
但是,如果我们准备扩大讨论范围以包括其他语言,那么在某些情况下goto
是一个好的解决方案,甚至是最好的解决方案。最常想到的场景是在没有结构化异常处理的语言中实现整理和错误处理。如果您仔细阅读 Linux 源代码,您会发现它goto
被广泛使用。我希望 Windows 源代码也是如此。
最初 GOTO 被添加到 Pascal 中用于错误处理,包括 Borland(/Embarcadero) 从未实现过的过程间形式(例如:从内部过程转到父级),就像 Borland 从未实现过其他内部函数功能,例如将内部函数传递给过程-类型参数。(*)
这样,GOTO 可以被认为是异常的前兆。
还有一些实际用途:我上次检查时,使用 goto 跳出嵌套的 IF 语句在 Delphi 中仍然更快,然后让代码自然地从嵌套的 if 中退出。像这样的优化有时用于压缩代码,以及其他具有深度嵌套循环或条件语句的复杂树处理代码。
这样的例程通常仍然使用 goto 进行错误处理,因为它更快。(异常不仅速度慢,而且它们的边界条件抑制了一些优化)。
可以将其视为 Object Pascal 的普通 Pascal 级别的一部分,就像 C++ 仍然几乎完全允许普通 C 一样。
(当然,由于Delphi中优化后的压缩代码只有.o格式,所以很难在Delphi代码库中找到示例。JPEG代码有一些,但那是C翻译)
(*) 原始帕斯卡和 IIRC 甚至 Turbo Pascal 都不允许使用 EXIT 过早退出程序。CONTINUE 和 BREAK 相同。
后藤很老了。它早于函数和过程等子例程!这也是非常危险的,并且会降低您的代码的可读性(对其他人或几个月后的您自己)。
从理论上讲,不可能出现需要 goto 的情况。我不会在这里重复有关图灵磁带机的理论,但是使用选择和迭代,您可以重新排序代码,以便在所有可能的输入值中产生相同的输出。
但在实践中,在某些条件下“跳离”代码流有时会“方便”且“可读性更好”,这就是异常出现的地方。raise
脱离当前执行,跳到最近的finally
部分except
。这是更安全的,因为它们是级联的,并且在出现这些边界条件之一的情况下提供了一种更好的方式来处理上下文。(还有break
andabort
和exit
)
就像 15 年前,我在 Delphi 中使用 goto 语句将Bob Jenkins 的哈希函数之一从 C 转换为 Pascal。C 函数有一个 switch() 语句,在每个 case 之后没有中断,而 Pascal 的 case 语句不能这样做。所以我把它转换成一堆 Pascal 标签和 goto。我猜您仍然必须使用最新的 Delphi 版本以相同的方式进行操作。编辑:我想使用 gotos 仍然是一种合理的方式来做到这一点。完成工作,易于理解,仅限于一小段代码,不危险。
GOTO
从来没有必要。任何可计算的算法都可以用赋值和IF
... THEN
、BEGIN
...的组合END
以及您选择的WHILE
... DO
...END
或REPEAT
...来表示UNTIL
。你甚至不需要子程序。:)
这被称为结构化程序定理。
如需证明,请参阅 Corrado Böhm 和 Giuseppe Jacopini 于 1966 年发表的论文Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules (PDF)。