大多数其他编程语言在条件语句的末尾不需要end if
语句。
if boolean_expression then statement else statement
包括end if
为Ada提供了其他语言所没有的优势是什么?
if boolean_expression then statement else statement end if
我认为如果条件为真(跳过代码的 else 部分),它与分支预测有关,但我不确定。
考虑一个嵌套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;
TL;博士:
它没有特别的优势,但它是任何允许块声明的语言的必要部分。
Ada 的块终止方法非常明确,但这并没有传达任何特别的优势。
讨论
正如其他人所指出的,这只是 Ada 的块终止方法。句法细节不是很重要,但语义很关键。
考虑一些如何用其他语言表示块终止的示例:
-
Erlang和Prolog:关键字
end
表示 lambda 和条件,句号字符.
用于函数定义,,
和;
表示短语分离。 - Python,YAML,"缩进模式">Haskell和RyuQ:块终止用缩进(语义空格)表示。
-
Ruby和Elixir:区块终止用关键字
end
表示。与艾达非常相似。 -
Algol和sh/Bash/Dash:快速块终止,与起始关键字的匹配反转。所以
if
以fi
终止,case
以esac
终止。 -
Rust,C,C++,D,Java,JavaScript/ECMA Script等:全部使用关键字和左括号打开
{
并使用闭}
关闭所有块,这允许轻松识别块的结束标记(通过相对幼稚的解析器,不一定是人类读者)。 -
Lisp和朋友们:一般来说,一切都是列表形式的语义表达式,所有评估块都用
(
打开(本质上意味着"开始评估"),而列表用'(
打开(本质上意味着"我是一个列表,但跳过评估我"),并且所有内容都以结束)
关闭。 -
XML,HTML,SGML,XSLT和其他醒着的噩梦:每个(可能是任意的)开始标签(如
<foo>
)都由一个匹配的标签终止,该标签带有</foo>
这样的结束斜杠指示器(有时只是</>
,由于重要原因,这稍微好一点)。尖括号疯狂的大多数变体现在也支持"自闭合"标签,其中结束斜杠可以作为速记存在于开始标签的末尾,因此像<foo></foo>
这样的空标签可以缩短为<foo />
或有时<foo/>
,具体取决于它碰巧是什么精神错乱的味道。(显然,有一些语义黑洞可以被这种歧义所吸引。
等。。。
正如我们所看到的,Ada 的块终止表达式一点也不奇怪——它只是比括号语言更明确(比 Erlang 和 Prolog 稍微明确一些)。无论如何,在不诉诸GOTO或其他形式的显式跳转表达式的情况下,绝对有必要能够定义逻辑块,这意味着也有明确的方法来终止它们。这只是艾达的方式。
增编:关于"区块"的说明
正如flyx善意指出的那样,语句,块,表达式,过程,子例程和函数之间存在有趣的区别。有些语言具有所有这些,有些只有函数和表达式,有些则具有任意组合。
C(及其后代)区分了"语句"和"表达式",在用大括号{}
分隔的C样式块的情况下,语言将该"块"视为单个语句。这意味着,它不会像表达式那样返回值,期望语句本身表示的过程的执行将对程序产生一些有意义的影响。
那么这在语法方面意味着什么?
在 Ada 中,if
显式打开一个块。
然而,在 C 语言中,if
根本不会打开或声明任何内容——它只是保护下一个语句。因此,在 C 语言中看到单行if
是完全正常的——根本不需要关闭括号,因为没有打开任何括号。但是,如果if
后面的语句需要是一个多行语句(请注意,在 C 中为每个多行语句定义函数有点不合时宜)。
if (x) {do_something();}
与
if (x) do_something();
看,妈,没有括号!
前者更常见,因为大多数条件分支都不止一行。
这个特定的问题在 C 三元运算符中变得更加模糊(现在您实际上确实遇到了分支预测问题):
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;
等等。
在这里,我们了解了未命名代码块的一些早期效用,以及在某些(但不是全部)语言中如何将它们视为复合语句。
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
此类代码要么可读性较差,可能容易出现范围问题,要么需要开发人员付出额外的努力。