简体   繁体   English

在Ada中定义通用标量类型包

[英]Defining a generic scalar-type package in Ada

I'd like to test the waters of writing Ada packages by making one for manipulating polynomials. 我想通过制作一个用于操作多项式的方法来测试编写Ada包的水域。 Polynomials can be defined for a wide class of algebraic structures, so to reflect this, I'd like to make the package generic, so it can be used with Floats, Integers, or other numeric sub-types. 可以为一大类代数结构定义多项式,因此为了反映这一点,我想使包通用,因此它可以与Floats,Integers或其他数字子类型一起使用。

I want to say now that I know very little about how Ada's type system work or how its package system works. 我现在想说的是,我对Ada的类型系统如何工作或它的包系统如何工作知之甚少。 There seems to be a lack of good beginner Ada inforamtion on the web, so I'm having to glean what wisdom I can from this not-so-newbie-friendly Wikibooks article. 网络上似乎缺乏良好的初学者Ada信息,因此我不得不从这篇不那么新手友好的Wikibooks文章中收集到我能够获得的智慧。

This page has some information about the type hierarchy. 页面包含有关类型层次结构的一些信息。 Based on that, it would seem that a reasonable type for my Polynomial package to be based on would be the Scalar type, since apparantly that's the one on which arithmetic operations are defined. 基于此,似乎我的Polynomial包的合理类型将是Scalar类型,因为显然是定义算术运算的类型。 So this is what I've attempted, in polynomials.ads : 所以这就是我在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;

However, this just nets me a "Scalar" is undefined error from GNAT. 但是,这只是让我知道"Scalar" is undefined GNAT的"Scalar" is undefined错误。

So far I've really just been feeling my way around half-blind, I don't actually know how any of this stuff works. 到目前为止,我真的只是半盲地感觉到了,我实际上并不知道这些东西是如何起作用的。 If I seem to have any major misconceptions that you think need to be cleared up, please tell me. 如果我认为你认为需要澄清任何重大误解,请告诉我。 Probably the easiest would be to provide example polynomial.ads and polynomial.adb code that I can learn from - just like a definition of the Polynomial type (with generic max-degree and element type) and a simple example function like adding two polynomials, so I can see how generic functions work. 可能最简单的是提供我可以学习的示例polynomial.adspolynomial.adb代码 - 就像多项式类型的定义(具有泛型max-degree和元素类型)和添加两个多项式的简单示例函数一样,所以我可以看到泛型函数是如何工作的。

PS: Sort of related, is there a way to define attributes for your user-defined types? PS:排序相关,有没有办法为用户定义的类型定义属性?

The problem is just that "Scalar" is not the name of a type. 问题只是“Scalar”不是类型的名称。

Looking at the section "Generic formal types" in that article I can't see one that imposes the exact restriction you want : "any scalar type". 看一下那篇文章中的“通用形式类型”部分,我看不到一个强加你想要的确切限制:“任何标量类型”。 Pity... Unless someone has a better idea, I would widen the declaration to: 可惜......除非有人有更好的主意,否则我会将声明扩大到:

type Element is private;

and carry on. 继续 This may not be a drawback : see the next section on generic formal subprograms, if you supply your own operators 这可能不是一个缺点:如果您提供自己的运算符,请参阅下一节关于通用正式子程序的部分

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

or 要么

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

you can then instantiate the generic for records (complex numbers?) matrices etc if it is meaningful to do so. 然后你可以实例化记录的通用(复数?)矩阵等,如果这样做有意义的话。 The "is <>" will use existing functions for types that already have them (Float etc) to simplify the instantiations "is <>"将使用已有函数的现有函数(Float等)来简化实例化

(Edit : forgot that scalar includes enumerations, for which polynomials or even multiplication, do not usually make sense! So widening it to "private" may not be such a drawback) (编辑:忘了标量包括枚举,多项式甚至乘法,通常没有意义!所以将它扩大为“私有”可能不是这样的缺点)

When you are defining a generic, what formal type you use defines what operations you have available inside the implementation of the generic. 在定义泛型时,您使用的正式类型定义了泛型实现中可用的操作。 You can always take Brian's option and use the (very nearly) most restrictive ( is private , which you can copy, but otherwise could be damn near anything), and then make the user define the routines you need. 您可以随时使用Brian的选项并使用(非常接近)最严格的( is private ,您可以复制,但在其他任何地方都可能是该死的),然后让用户定义您需要的例程。 This is in fact the only way to make a single generic that can perform math on any scalar. 实际上,这是制作可以在任何标量上执行数学运算的单一泛型的唯一方法。

Ada's generic formal scalar type system is divided into the following rough hierarchy: Ada的通用正式标量类型系统分为以下粗略层次结构:

  • There are discretes ( (<>) ), floating point values ( digits <> ), and fixed point values ( delta<> ). 有离散值( (<>) ),浮点值( digits <> )和固定点值( delta<> )。
    • Within the discretes, there are signed integers ( range <> ) and modular integers ( mod <> ) (enumerated types are also discretes, but they can only be handled as discretes). 在离散值中,有符号整数( range <> )和模块整数( mod <> )(枚举类型也是离散的,但它们只能作为离散值处理)。

An important implication of this is that there is a way to make a generic that can take both integers and enumerations ("discretes"), but there is no way to make a generic that can operate on both integers and floats. 这样做的一个重要含义是,有一种方法可以创建一个可以同时采用整数和枚举(“离散”)的泛型,但是没有办法制作一个可以对整数和浮点运算的泛型。 Instead you either have to make one for each, or fake it out with privates and passed in math operators, like Brian's answer showed. 相反,你要么必须为每个制作一个,要么用私有伪造,并传递给数学运算符,就像Brian的答案所示。

In practice I haven't found this too much of a problem. 在实践中,我没有发现太多问题。 The instances where I want to work with floating-point values tend to be very different than those where I want to work with integers. 我想使用浮点值的实例往往与我想要使用整数的实例非常不同。 For instance, in this case, how useful would your "polynomial" generic really be for 32-bit integers? 例如,在这种情况下,你的“多项式”泛型对于32位整数有多大用处? Very few calculated results would be exact integers. 很少有计算结果是精确整数。

This is sort of a cultural issue. 这是一种文化问题。 Many languages (led by C) consider Integers and Floating-point types to be closely related things, and make them easily interchangable (sometimes even silently). 许多语言(由C领导)认为整数和浮点类型是密切相关的东西,并使它们易于互换(有时甚至是无声的)。 In Ada, they are two totally different universes, and you should get used to thinking of them that way. 在阿达,它们是两个完全不同的宇宙,你应该习惯于这样思考它们。 It is true that it isn't too big of a pain to convert an integer into a floating-point value, and the floating point types have ways to truncate or round their values to the nearest integer. 确实,将整数转换为浮点值并没有太大的痛苦,浮点类型有办法将它们的值截断或舍入到最接近的整数。 For the most part though, you should keep your integers (discretes) and your floating-point values separated. 但是,在大多数情况下,您应该保持整数(离散值)和浮点值分开。

So for me, I'd just define it with 所以对我来说,我只是定义它

type Element is digits <>;

...and go on my merry way. ......继续我的快乐方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM