以下是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特性如多态性需要进一步研究考证),而且有大量的类型定义和处理特性和面向对象特性有待探索。