If statement 为什么ada中的if表达式和if语句也是case

If statement 为什么ada中的if表达式和if语句也是case,if-statement,ada,If Statement,Ada,摘自: Ada的if表达式类似于if语句。但是,由于它是一个表达式,因此存在一些差异: 所有分支的表达式必须是同一类型 如果周围的表达式尚未包含圆括号,则必须用圆括号括起来 除非then后面的表达式具有布尔值,否则else分支是必需的。在这种情况下,else分支是可选的,如果不存在,则默认为else True 我不理解使用if关键字构建代码需要两种不同的方法。这背后的原因是什么 还有case表达式和case语句。这是为什么?我认为最好引用《2012年美国残疾人法案》的基本原理来回答这个问题: W

摘自:

Ada的
if
表达式类似于
if
语句。但是,由于它是一个表达式,因此存在一些差异:

所有分支的表达式必须是同一类型

如果周围的表达式尚未包含圆括号,则必须用圆括号括起来

除非
then
后面的表达式具有布尔值,否则
else
分支是必需的。在这种情况下,else分支是可选的,如果不存在,则默认为
else True

我不理解使用
if
关键字构建代码需要两种不同的方法。这背后的原因是什么


还有
case
表达式和
case
语句。这是为什么?

我认为最好引用《2012年美国残疾人法案》的基本原理来回答这个问题:

WG9指导文件[1]确定的关键领域之一是 需要注意的是提高写作和执行的能力 合同。上一章详细讨论了这些问题。 定义前提条件、后条件的新方面时,请键入 不变量和子类型谓词很明显,如果没有更多 灵活的表达形式,许多函数需要 因为在所有情况下,方面都是由表达式给出的。 但是,声明一个函数,从而给出 函数体中的条件、不变量或谓词使 合同的细节对人类读者来说相当遥远。问询处 隐藏通常是一件好事,但在这种情况下,它只会引入 默默无闻。介绍了四种形式,即if表达式、case 表达式、量化表达式和表达式函数。在一起 它们给Ada一些函数式语言的灵活感觉

此外,
if
语句和
case
语句通常为所有分支中的同一变量分配不同的值,除此之外:

if Foo > 10 then
   Bar := 1;
else
   Bar := 2;
end if;
在这种情况下,
if
表达式可能会增加可读性,并在代码中更清楚地说明发生了什么:

Bar := (if Foo > 10 then 1 else 2);
我们现在可以看到,代码的维护者不再需要阅读整个
if
语句来查看只更新了一个变量

case
表达式也是如此,这也可以减少嵌套
if
表达式的需要


此外,我还可以向您提出一个问题:为什么基于C的语言除了if语句之外还有三元运算符
?:

Egilhh已经介绍了主要原因,但有时还有其他有用的原因来实现表达式。有时,您制作的包只需要一个或两个方法,它们是制作包体的唯一原因。可以使用表达式生成表达式函数,这些函数允许您在等级库文件中定义操作

此外,如果您最终得到一些复杂的变量记录组合,有时可以使用表达式为它们设置默认值,而在这些情况下,您通常无法如此清晰地创建它们。考虑下面的例子:

with Ada.Text_IO; use Ada.Text_IO;

procedure Hello is

    type Binary_Type is (On, Off);

    type Inner(Binary : Binary_Type := Off) is  record
        case Binary is
            when On =>
                Value : Integer := 0;
            when Off =>
                null;
        end case;
    end record;

    type Outer(Some_Flag : Boolean) is record
        Other : Integer := 32;
        Thing : Inner   := (if Some_Flag then 
                              (Binary => Off) 
                            else 
                              (Binary => On, Value => 23));
    end record;

begin
  Put_Line("Hello, world!");
end Hello;

我想出了一个更复杂的设置,旨在在硬件级别映射到复杂的消息传递接口。只要有可能就有默认值是很好的。现在我已经在Outer内部使用了一个case,但是接下来我必须为每个case提供消息字段的两个单独命名的版本,当您希望代码映射到ICD时,这并不是最佳的。同样,我也可以使用一个函数来初始化它,但正如其他海报回答中所指出的,这并不总是一个好方法。

另一个概述了向Ada添加条件表达式动机的地方可以在ARG文档中找到,该文档解释了动机并给出了一些使用示例

我发现它们非常有用的一个例子是在处理命令行参数时,如果没有在命令行上指定参数,则使用默认值。通常,您希望在程序中将这些值声明为常量。条件表达式更容易做到这一点

with Ada.Command_Line; use Ada;

procedure Main
is
   N : constant Positive :=
     (if Command_Line.Argument_Count = 0 then 2_000_000
      else Positive'Value (Command_Line.Argument (1)));
   ...
否则,如果没有条件表达式,为了达到同样的效果,您需要声明一个函数,我发现这更难理解

with Ada.Command_Line; use Ada;

procedure Main
is

   function Get_N return Positive is
   begin
      if Command_Line.Argument_Count = 0 then
         return 2_000_000;
      else
         return Positive'Value (Command_Line.Argument (1));
      end if;
   end Get_N;

   N : constant Positive := Get_N;
   ...

需要强调的是,由于Ada经常用于关键软件中,在这些软件中,代码覆盖率证明可能是强制性的(),因此这种构造可能被禁止(它隐藏了源代码覆盖率的决策节点)。除非您能够提供目标代码覆盖范围并正式证明您达到了每个相应的说明(在这两种情况下,您可能需要工具资格来提供此类证明)。