ADA程序实例(类型、控制流、转换、简单数学运算等)
以下是ADA实现的质因数分解程序,其等价C#程序可见:
http://topic.csdn.net/u/20111112/18/2bf17a93-862d-458e-91d7-8682dc899315.html
(由于没有专门的ADA代码显示模板,只能选择最相近的Delphi模板,故关键字标识会不正常)
首先是功能单元模块(package)的声明文件(prime-factors-resolver.ads):
with Ada.Containers.Doubly_Linked_Lists; use Ada.Containers; package prime_factors_resolver is -- instantiate a generic package and use its content package Int_List is new Doubly_Linked_Lists(Integer); use Int_List; function resolve(number : Integer) return List; end prime_factors_resolver;
接下来是功能单元的实现文件(prime-factors-resolver.adb):
with Ada.Text_IO; use Ada.Text_IO; with Ada.Numerics.Generic_Elementary_Functions; use Ada.Numerics; package body prime_factors_resolver is package Float_Functions is new Generic_Elementary_Functions(Float); use Float_Functions; function resolve(number : Integer) return List is list_of_factors : List; list_of_primes : List; -- list of primes encountered so far k : Integer := 2; -- prime number starts from 2 value: Integer; begin if number < 2 then list_of_factors.Append(number); return list_of_factors; end if; value := number; -- see, ada supports this also now in its latest version -- originally it had to be Append(list_of_primes, k); list_of_primes.Append(k); mainloop: -- named loop for specific quiting while true loop if value = k then -- value is k straight list_of_factors.Append(k); exit mainloop; -- exit specific loop (in this case the immediate loop) elsif value rem k = 0 then -- value is divisible by k Append(list_of_factors, k); value := value / k; else -- value is greater than and indivisible by k declare -- make use of block to declare block-wide variables is_prime: Boolean := true; prime_number : Integer; begin if k = 2 then k := 1; -- go backwards by one for this special case end if; loop -- loop to find the prime number next to k k := k + 2; is_prime := true; for prime_cursor in list_of_primes loop prime_number := element(prime_cursor); if k rem prime_number = 0 then is_prime := false; exit; elsif prime_number > Integer(Float'Floor(Float(k)**0.5)) then exit; end if; end loop; exit when is_prime; -- this is equivalent to 'until' condition end loop; -- the next prime number found list_of_primes.Append(k); end; end if; end loop mainloop; return list_of_factors; end resolve; begin put_line("Resolver successfull loaded."); end prime_factors_resolver;
最后是调用这个模块的主程序(main.adb):
with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with prime_factors_resolver; use prime_factors_resolver; use prime_factors_resolver.Int_List; -- have to be that defined immediately procedure main is user_input : String(1..32) := 32 * " "; -- a way to create string with spaces user_input_len : Integer; number : Integer; list_of_factors : Int_List.List; factor : Integer; -- the value of the item the cursor pointing to first_factor : Boolean := true; begin put("Input a number: "); get_line(user_input, user_input_len); number := Integer'Value(user_input); -- a system provided way of conversion put(number); put(" = "); list_of_factors := resolve(number); for factor_cursor in list_of_factors loop factor := Element(factor_cursor); if first_factor then first_factor := false; else put(" * "); end if; put(factor, 0); -- 0 to indicate leaving no spaces around the number end loop; end main;
这里面有几点注意,(以前学的时候也可能忽略,有些可能是近期ADA版本的新属性)
1. ADA最新版本支持以对象Instance为主体的方法调用(可以像C#和Java那样用点“.”来访问对象的方法),就像以上的Append方法,但条件是这个方法定义的第一参数(潜在的接入主体)必须是tagged定义的record,即使能了object oriented的ADA数据。例如对Cursor类型的Element方法就不能这样用,因为Cursor没有tagged。
2. ADA中使用一个功能提供者的交互的数据结构(就像函数参数,返回值),其类型需要从这个功能提供者这边直接得到,而不是从源头得到,就像例子中的List。这和C#是不一样的(对我而言我倒更接受ADA这种处理,虽然有时有些麻烦了点)。
3. 泛型包(Generic Package)的实例化要加new关键字。
4. 好多Attribute要记(ADA里的Attribute指一种基于类型的功能方法,他们都是系统内建的(还是可能供用户定义?可能性不大))。
5. ADA的运算符重载的广度肯定在C#之上(但,当然,在C++之下:))。
6. ADA的可带类型限制的泛型定义的广度和表达力极可能完全在C#之上。
从这个例子可以看出ADA十分严谨(我认为它是世界上最严谨的语言),而功能全面超越所有Pascal系语言(除了一些OO特性如多态性需要进一步研究考证),而且有大量的类型定义和处理特性和面向对象特性有待探索。