Ada语言中的end if语句相较于其他语言有什么优势?

4
大多数其他编程语言在条件语句结尾处不需要使用 end if 语句。
if boolean_expression then statement else statement

包含 end if 在 Ada 中提供的优势是什么,其他语言没有吗?
if boolean_expression then statement else statement end if

我认为这与分支预测有关,如果条件为真(跳过代码的else部分),但我不确定。


1
正如您可以在Rosetta code上查看的那样,所有编程语言都使用缩进来界定if块,使用字符(例如{})来界定块,或者具有等效于end if的东西。 - Faibbus
1
分支预测与此无关,这只是Ada语言终止块的方式。 - Dave Newton
在其他使用大括号的编程语言中,例如,如果有多个嵌套级别,你最终会得到一堆},你可能无法确定哪个大括号结束了哪个块,顶部可能超出屏幕。在Ada中,“end if;”或“end if Label_Name;”通过查看正在结束的内容,您可以轻松地确定。Ada关注可读性。 - Luke A. Guest
3个回答

9
考虑一个嵌套的if,像这样:if boolean_expression then if another_boolean_expression then statement else statement 现在,else部分属于哪个if语句? end if解决了这个问题(为了清晰起见进行了缩进):
if boolean_expression then 
   if another_boolean_expression then
      statement 
   end if;
else
  statement 
end if;

或者:

if boolean_expression then 
   if another_boolean_expression then
      statement
   else
      statement
   end if;
end if;

2
这个问题的维基百科链接:https://zh.wikipedia.org/wiki/%E6%82%AC%E7%A9%BA_else - flyx

4

TL;DR:

它没有特殊优势,但对于允许块声明的任何语言来说都是必要的一部分。

Ada的块终止方法非常明确,但这并没有传达任何特定的优势。

Discussion

正如其他人所指出的那样,这只是Ada的块终止方法。 语法细节并不是非常重要,但语义至关重要。

考虑一些其他语言中如何表达块终止的示例:

  • ErlangProlog:lambda和条件语句使用关键字end,函数定义使用句点字符.,短语分隔使用逗号,和分号;
  • PythonYAML、缩进模式的HaskellRyuQ:块终止使用缩进(语义空格)。
  • RubyElixir:块终止使用关键字end。与Ada非常相似。
  • Algolsh/Bash/Dash:使用匹配反转的起始关键字来表示块终止。因此,iffi结束,caseesac结束。
  • RustCC++DJavaJavaScript/ECMA Script等:所有块都使用关键字和开放括号{打开,并使用关闭}关闭所有块,这使得块的关闭标记可以轻松地被识别(由相对简单的解析器,而不一定是人类读者)。
  • Lisp及其衍生语言:一般来说,所有表达式都是列表形式的语义表达式,并且所有评估块都使用(打开(这基本上意味着“开始评估”),而列表则使用'(打开(这基本上意味着“我是一个列表,但跳过对我的评估”),并且所有列表都使用闭合括号)关闭。
  • XMLHTMLSGMLXSLT和其他令人噩梦的标记语言:每个(可能是任意的)开放标记,如<foo>,都由带有结束斜杠指示符的匹配标记终止,如</foo>(或者有时只是</>,出于重要原因,稍微好一点)。大多数变种的尖括号狂热现在也支持“自关闭”标记,其中关闭斜杠可以存在于开放标记的末尾作为缩写,因此像<foo></foo>这样的空标记可以缩短为<foo />或者有时取决于它所属的疯狂类型<foo/>。(显然,这种模棱两可的语义黑洞有一些可能会吸引你。)
我們可以看到,Ada的塊終止表達式並不奇怪 - 它只是比方括號語言更明確(略微比Erlang和Prolog更明確)。無論如何,為了不使用GOTO或其他形式的顯式跳轉表達式,絕對有必要能夠定義邏輯塊,這也意味著必須有一種清晰的終止它們的方式。這就是Ada的方式。
附錄:關於“塊”的說明
正如flyx所指出的,語句、塊、表達式、過程、子程序和函數之間有一個有趣的區別。一些語言擁有所有這些,一些只有函數和表達式,一些則具有任意混合。
C(及其後代)區分“語句”和“表達式”,在由{}大括號界定的C風格塊的情況下,該“塊”被視為單個語句。這意味著,它不會像表達式那樣返回值,而是期望表示語句本身的過程執行對程序產生某些有意義的影響。
那在語法上意味著什麼?
在Ada中,if明確地打開一個塊。
在C语言中,if语句并不会打开或声明任何东西——它只是简单地保护下一条语句。因此,在C语言中看到单行的if语句是很正常的——不需要关闭任何括号,因为没有打开。但是,如果if语句后面的语句需要是多行语句(请注意,在C语言中为每个多行语句定义函数有点不符惯例)。
if (x) {do_something();}

是同样的意思

if (x) do_something();

看,妈妈,没有括号!

前者更常见,因为大多数条件分支不止一行。

这个特定问题变得有点模糊(现在你实际上涉及到分支预测问题)与C ternary operator

int opening_time = (day == SUNDAY) ? 12 : 9;

或者Python最近添加的三元运算符:
opening_time = 12 if day == 'sunday' else 9

一个等价的(在某种程度上不太习惯的 C 语言):
int opening_time = 9;
if (day == SUNDAY) opening_time = 12;

等等就是这样。

这里我们开始理解一些早期未命名代码块的实用性,并且了解在一些(但不是全部)编程语言中它们如何被视为复合语句


1
不是我点踩的,但如果你解释代码块,应该提到在大多数使用 {} 表示代码块的语言中,if 语句被定义为仅在满足条件时执行 下一个语句。因此,当您想有条件地执行多个语句时,使用块作为 if 后面的语句,因为 块是一条语句。这与 Ada 不同,因为 if 语句 自动开始一个块 - flyx
@flyx 很好的观点。在C和类C语言中,一行if语句中根本没有括号--这确实需要一些解释。 - zxq9
错过了一个重点,即使用以块类型“if”和/或标签结尾的限定符可以帮助编译器确定块终止符的缺失位置。这在花括号中并不总是可决定的。 - ktb

3

Ada语言的设计考虑到可读性和代码缺陷预防。因此,作用域关闭结构是必需的,并与作用域开放结构相对应。当您有一段很长的代码时,更容易弄清楚该关闭条目实际上关闭了什么。

procedure Foo is
begin
    if condition then 
    -------------------
    -- a lot of code...
    -------------------
    end if;
end Foo;

相比之下,其他语言的语法可能会让开发人员自行决定是否编写附加注释以澄清结束条目的目的,或者是否完全编写结束条目(例如C ++):

void
Foo(void)
{
    if(condition)
    {
    ///////////////////
    // a lot of code...
    ///////////////////
    } // if
} // Foo

这样的代码可能不易读,并且潜在地存在作用域问题,或者需要开发人员额外付出努力。

1
是的,就像我上面写的那样。另外,正如你在这里指出的那样,许多其他语言使用}后的注释来解释正在关闭的内容,如果你忘记放置或者你的IDE没有为你完成它怎么办?Ada强制执行它。 - Luke A. Guest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接