3

我想通过制作一个用于操作多项式的包来测试编写 Ada 包的能力。多项式可以为广泛的代数结构定义,为了反映这一点,我想使包通用,以便它可以与浮点数、整数或其他数字子类型一起使用。

我现在想说的是,我对 Ada 的类型系统如何工作或它的包系统如何工作知之甚少。网络上似乎缺乏好的初学者 Ada 信息,所以我不得不从这篇对新手不太友好的 Wikibooks 文章中收集我能获得的智慧。

页面包含有关类型层次结构的一些信息。基于此,我的多项式包所基于的合理类型似乎是Scalar类型,因为显然这是定义算术运算的类型。所以这就是我尝试过的,在polynomials.ads

generic

    MAX_DEGREE : Positive;
    type Element is new Scalar;

package Polynomial is

    type Polynomial is Array (0 .. MAX_DEGREE) of Element;

end Polynomial;

然而,这只是给我带来了"Scalar" is undefinedGNAT 的错误。

到目前为止,我真的只是半盲的感觉,我实际上不知道这些东西是如何工作的。如果我似乎有任何您认为需要澄清的重大误解,请告诉我。可能最简单的方法是提供我可以从中学习的示例polynomial.adspolynomial.adb代码 - 就像多项式类型的定义(具有通用最大度数和元素类型)和一个简单的示例函数(例如添加两个多项式),所以我可以看到通用性功能起作用。

PS:有点相关,有没有办法为您的用户定义类型定义属性?

4

2 回答 2

7

问题只是“标量”不是类型的名称。

查看该文章中的“通用形式类型”部分,我看不到一个施加您想要的确切限制的部分:“任何标量类型”。可惜......除非有人有更好的主意,否则我会将声明扩大到:

type Element is private;

并继续。这可能不是一个缺点:如果您提供自己的运算符,请参阅下一节通用形式子程序

with function "*" (X, Y: Element) return Element;

或者

 with function "*" (X, Y: Element) return Element is <>;

然后,如果有意义的话,您可以实例化记录(复数?)矩阵等的泛型。"is <>"将对已经拥有它们的类型(Float 等)使用现有函数来简化实例化

(编辑:忘记了标量包括枚举,多项式甚至乘法通常没有意义!因此将其扩展到“私有”可能不是这样的缺点)

于 2012-11-16T13:41:45.637 回答
6

在定义泛型时,使用的正式类型定义了泛型实现中可用的操作。您始终可以选择 Brian 的选项并使用(几乎)最严格的 ( is private,您可以复制它,但否则可能会接近任何东西),然后让用户定义您需要的例程。实际上,这是制作可以对任何标量执行数学运算的单个泛型的唯一方法。

Ada 的通用形式标量类型系统分为以下粗略的层次结构:

  • 有离散(<>)值 ( )、浮点值 ( digits <>) 和定点值 ( delta<>)。
    • 在离散内,有带符号整数 ( range <>) 和模整数 ( mod <>)(枚举类型也是离散的,但它们只能作为离散处理)。

这一点的一个重要含义是,有一种方法可以制作一个可以同时接受整数和枚举(“离散”)的泛型,但是没有办法制作一个可以同时对整数和浮点数进行操作的泛型。相反,您要么必须为每个人制作一个,要么用私人伪造它并传入数学运算符,就像布赖恩的回答所示。

在实践中,我没有发现这有太大的问题。我想要使​​用浮点值的实例往往与我想要使用整数的实例非常不同。例如,在这种情况下,您的“多项式”泛型对于 32 位整数真的有用吗?很少有计算结果是精确的整数。

这是一个文化问题。许多语言(以 C 为主导)认为整数和浮点类型是密切相关的事物,并使它们易于互换(有时甚至是无声的)。在 Ada 中,它们是两个完全不同的宇宙,你应该习惯于这样想它们。确实,将整数转换为浮点值并不太麻烦,并且浮点类型有办法将它们的值截断或舍入到最接近的整数。不过,在大多数情况下,您应该将整数(离散)和浮点值分开。

所以对我来说,我只是定义它

type Element is digits <>;

...继续我的快乐之路。

于 2012-11-16T15:10:18.637 回答