在 1970 年代,许多编程语言都专门针对它们控制的硬件。 因此,开发人员必须学会根据他们正在编程的硬件以不同的方式进行编码。 调试和维护高度专业化,并且代码无法在机器之间重用。
英国政府认识到这些问题,并朝着建立标准化的多用途编程语言的方向发展。 1980 年 12 月 10 日(阿达·洛芙莱斯生日),他们将 Ada 编程语言定为英国的官方军事标准。
Ada 在某些方面与 Algol 或 Pascal 相似。 它最初是为程序可靠性、易于维护和效率而设计的。 然而,最重要的是,Ada 的创建者认识到编码是一项人类活动,因此编程语言必须是人类可以轻松阅读和交互的东西。
对于 Ada 来说,可读性比简洁性更重要。 与 Python 相比,用 Ada 编写代码可以产生高度可读的代码,尽管它的用途往往是专门的,但 Ada 今天仍在开发中。
安装 Ada
Ada 的工具链是 GNU Ada 开发环境,更广为人知的名称是 GNAT。
您可以使用发行版的包管理器在 Linux 上安装 GNAT。 在 Fedora、CentOS 或类似系统上
$ sudo dnf install gcc-gnat
在 Debian、Linux Mint 及其衍生版本上
$ sudo apt install gnat
在 macOS 和 Windows 上,您可以从 Adacore 网站 下载安装程序(从下拉菜单中选择您的平台)。
程序单元
Ada 代码由程序单元组成。 有许多不同类型的程序单元,但是编码时花费最多时间的单元是子程序。 子程序是一种算法。 在 Ada 中,子程序可以是过程或函数。 过程没有返回值,而函数有返回值。
如何在 Ada 中编写过程
在文本编辑器中创建一个文件,然后输入这段简单的 Ada 代码
with Ada.Text_IO; use Ada.Text_IO;
procedure hello is
begin
Put_Line ("Happy Ada Lovelace day.");
end hello;
将文件保存为 hello.adb.
第一行使用关键字 with
,这类似于其他语言中的 import
或 include
语句。 这 使程序可以使用 test_io
Ada 库。
下一行定义了一个过程,这是 Ada 对自包含算法的一个非常直观的术语。 过程被命名,然后用关键字 begin
和 end.
分隔。
要运行此示例程序,请运行 gnatmake.
$ gnatmake hello.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali
可执行应用程序放置在当前目录中,并带有过程的名称。 运行它以查看结果。
$ ./hello
Happy Ada Lovelace day.
变量
Ada 是一种强类型语言,这意味着在创建变量时,必须声明它可以包含的数据类型。 必须先声明变量才能使用它。
with ada.Text_IO;
use Ada.Text_IO;
procedure Main is
myString: String := "Hello world";
begin
Put_Line ( myString );
end Main;
如果不知道变量的内容,可以在声明它之后再设置其内容。
procedure Main is
myNumber: Integer;
begin
myNumber := 123;
end Main;
如果您习惯于动态类型语言(例如 Python),这些语言会尝试根据在变量中找到的数据来调整处理数据的方式,那么像 Ada 这样的强类型语言可能会给您带来一些令人沮丧的意外。
例如,尝试使用 Put_Line
打印整数会失败,因为 Put_Line
需要一个字符串。 如果您有一种类型的数据,想要将其视为另一种类型,则必须执行类型转换。 在 Ada 中,从一种类型转换为字符串类型使用 'Image
属性。
with ada.Text_IO;
use Ada.Text_IO;
procedure Main is
myNumber: Integer;
begin
myNumber := 123;
Put_Line ( Integer'Image (myNumber) );
end Main;
有几种 不同的转换可用,您使用哪种转换取决于给定任务所需的数据类型。
循环
Ada 中存在所有常用的流程控制机制。 有 if/else 语句、case 语句、while 循环、for 循环等等。
while 循环类似于其他语言中的 while 循环,并且可以使用相同的技巧来控制它。 例如,通常创建一个设置为 0 的变量,在循环的每次迭代中将该变量递增一次,然后仅在变量小于特定值时运行循环。
with ada.Text_IO; use Ada.Text_IO;
procedure Main is
myString: String := "Hello";
myCount: Integer := 0;
begin
-- while loop
while myCount < 3 loop
Put_Line ( myString );
myCount := myCount + 1;
end loop;
end Main;
这将输出
$ ./main
Hello
Hello
Hello
for 循环使用一个临时变量(在本例中为 I
)来存储来自循环迭代的数组或范围的数据。 没有必要递增,因为这对于 for 循环来说是隐式的。
with ada.Text_IO;
use Ada.Text_IO;
procedure Main is
begin
for I in 0 .. 3 loop
Put_Line (Integer'Image (I));
end loop;
end Main;
这将输出
$ ./main
0
1
2
3
如何在 Ada 中编写函数
Ada 在设计时考虑了模块化,因此很容易编写小的代码片段,然后将它们连接成更大的应用程序。 函数由声明和定义组成。
在您喜欢的文本编辑器中打开一个文件,然后添加此声明
function Double_Integer (I : Integer) return Integer is
您已经通过给它一个名称 (Double_Integer
)、指定一个参数(一个名为 I
的整数)并列出其返回类型(一个整数)来声明一个函数。 现在必须定义函数的作用。 函数定义是一个子程序,就像过程一样,只不过它返回一个值。
将此简单代码添加到文件中
begin
return I + I;
end Double_Integer;
将此文件保存为 double_integer.adb.
要使用您的函数,必须使用 with
关键字将其包含在您的应用程序中。 打开一个名为 main.adb
的新文件,并包含您的自定义函数。
with ada.Text_IO;
use Ada.Text_IO;
with Double_Integer;
在 Ada 中,不能将函数作为独立语句调用。 您可以通过将函数的输出分配给变量来调用函数。
在此代码块中,myResult
变量接收 Double_Integer
函数的结果。
procedure Main is
myResult: Integer := 0;
begin
myResult := Double_Integer (9);
Put_Line (Integer'Image (myResult));
end Main;
保存此文件,然后编译它。
$ gnatmake main.adb
GNAT 会自动发现 double_integer.adb
并包含它,并且您的应用程序会被编译。 要翻倍的值已硬编码到应用程序中,因此请运行它以查看结果。
$ ./main
18
命令行参数
GNAT 工具链不仅提供编译器。 它还提供了一些可以在 Ada 代码中使用的有用库。 一个特别好的库是 GNAT.Command_Line
函数,它允许您的 Ada 程序接受 选项和参数。
这是一个简单的例子
with GNAT.Command_Line; use GNAT.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
begin
loop
case Getopt ("a b:") is
when 'a' =>
Put_Line ("Got a Boolean");
when 'b' =>
Put_Line ("Got an argument: " & Parameter);
when others =>
exit;
end case;
end loop;
Put_Line ("File argument was " & Get_Argument);
end Main;
从阅读代码可以看出,在 Ada 中解析选项在很大程度上是一个手动过程。
Parameter
和 Get_Argument
变量由 GNAT.Command_Line
函数提供,其余的只是使用循环来迭代传递给命令的命令行参数的问题。
运行代码会产生以下输出
$ ./main -a -b foo file.txt
Got a Boolean
Got an argument: foo
File argument was file.txt
掷骰子演示
这些只是复杂语言的基础知识,但为了演示它是如何组合在一起的,这是一个简单的掷骰子应用程序。
首先,创建一个返回随机数的函数。 这使用 Ada.Numerics.Discrete_Random
库,该库具有其特性,但 Ada 的网站上有一个简单的演示和解释。 此函数与 Ada 文档站点上该库的基本演示非常相似,除了它接受一个参数(整数 I
)作为随机范围的上限。
创建一个名为 random_number.adb
的文件,并在其中包含此代码
with Ada.Numerics.Discrete_Random;
function Random_Number (I : Integer) return Integer is
subtype Random_Range is Integer range 1 .. I;
package R is new Ada.Numerics.Discrete_Random (Random_Range);
use R;
G : Generator;
X : Random_Range;
begin
Reset (G);
X := Random (G);
return X;
end Random_Number;
接下来,创建应用程序本身,该应用程序接受一个数字来确定要掷的虚拟骰子有多少个面,然后调用随机数函数,并将用户提供的整数传递给该函数。
它将掷骰子的结果打印到终端。
with GNAT.Command_Line; use GNAT.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
with Random_Number;
procedure Main is
ROLL: Integer;
begin
loop
case Getopt ("d:") is
when 'd' =>
-- random number
ROLL := Random_Number(Integer'Value(Parameter));
Put_Line ("You roll: " & Integer'Image(ROLL));
when others =>
exit;
end case;
end loop;
end Main;
编译它,
$ gnatmake main.adb
并进行测试。
$ ./main -d 20
14
$ ./main -d 20
3
$ ./main -d 4
2
$ ./main -d 6
5
看起来不错!
学习 Ada
Ada 是一种独特的、高度结构化的语言,拥有一支敬业的开发人员队伍,尤其是在 嵌入式领域。
无论您是否可以想象将 Ada 用作专用硬件的语言,您对类似于 Algol 和 Pascal 的语言感兴趣,还是想要进行有趣的实验,您都可以在 Awesome Ada Github 页面上探索这个语言的狂野世界。
评论已关闭。