Ada 通用包管理?

Ada 通用包管理?,ada,Ada,我刚刚开始使用Ada,我发现通用包声明相当愚蠢。也许我做得不对,所以我在寻找更好的选择 看看下面的例子 package STD_Code_Maps is new Ada.Containers.Map(Key_Type => STD_Code_Type; Element_Type => Ada.Strings.Unbounded.Unbounded_String); STD_Code_Map : STD_Code_Maps.Ma

我刚刚开始使用Ada,我发现通用包声明相当愚蠢。也许我做得不对,所以我在寻找更好的选择

看看下面的例子

package STD_Code_Maps is new
   Ada.Containers.Map(Key_Type     => STD_Code_Type;
                      Element_Type => Ada.Strings.Unbounded.Unbounded_String);
STD_Code_Map : STD_Code_Maps.Map;

-- . . .

procedure Do_Something is
   Item : Ada.Strings.Unbounded.Unbounded_String;
begin
   Item := STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
   -- Do something with the Item
   -- . . .
end Do_Something;
如果能够简单地编写
STD_-code_-Map.First.Element
,而不是被遗弃的
STD_-code_-Map.Element(STD_-code_-Map.First(STD_-code_-Map)),那就更干净了

显然我做错了,我想。我在那里至少重复了三次STD_代码_地图这个短语。我完全赞成冗长和一切,但实际上我写的代码对我来说是糟糕和愚蠢的

我想知道是否有解决方案不要求您将包重命名为
包映射重命名STD\u code\u映射这当然会缩短代码,但我不想在每个过程条目上都这样做。我真的认为像
STD\u code\u Map.First.Element
这样的东西会简单得多。这能在2012年完成吗

注意:默认情况下使用无界_字符串包也很困难。标准库设计者是否真的对荒谬且过长的包层次结构给予了很多考虑


感谢您阅读本文,并有可能帮助我。我是Ada的新手。

Ada是为可读性和可维护性而设计的。(写一次,读和维护更长时间)这意味着它有时会变得有点冗长。如果你喜欢简洁和神秘的语言,还有很多其他的语言

如果要避免一直键入STD_Code_Map,只需使用use子句:

use STD_Code_Map;
这意味着你的行为准则

   Item := STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
将成为

   Item := Element(First(STD_Code_Map));

GNAT GPL 2012和2013以及FSF GCC 4.7和4.8支持Ada 2012的新容器索引方案,这意味着您可以编写

Item := STD_Code_Map ({some Cursor});
Item := STD_Code_Map (STD_Code_Map.First);
您甚至可以使用
-gnat05
开关来强制Ada 2005模式!(这一定是个bug)

Ada 2005允许您使用
object.function
表示法调用标记类型的基元函数,前提是第一个操作数为标记类型;因此,您可以编写
STD\u-code\u-Map.First
作为
STD\u-code\u-Map.First(STD\u-code\u-Map)
的缩写

把这些放在一起,你就可以写了

Item := STD_Code_Map ({some Cursor});
Item := STD_Code_Map (STD_Code_Map.First);

这很短

这个问题与泛型无关。正如Simon指出的,您可以说STD_Code_Map.First,因为STD_Code_Map的类型是标记类型,Ada支持标记类型的这种表示法。另一方面,STD_Code_Map.First的类型是一种游标类型,它没有标记(将其标记会导致声明同时使用游标和映射的某些操作时出现问题)。但是即使没有Simon提到的Ada 2012容器索引,您也可以说

STD_Code_Maps.Element(STD_Code_Map.First);
哪个好一点。除了重命名包外,还可以重命名函数:

function Elem (Position : STD_Code_Maps.Cursor) return STD_Code_Maps.Element_Type
    renames STD_Code_Maps.Element;

现在,只要可以直接看到重命名,就可以使用
Elem
而不是
STD\u code\u Maps.Element
。(如果您愿意,可以将其称为
元素
。重命名名称可以相同,也可以不同。)如果您经常使用该函数,这可能会很有帮助。

在Ada中获得良好且可读的名称有时会很棘手。通常情况下,语言设计人员通过设计与Ada
use
子句一起使用的Ada标准库包,而没有考虑到他们会如何看待一些不能或不想使用该功能的可怜sap,从而使任务变得更糟

不过在这种情况下,有些事情你可以自己做

例如“_Maps.Map”是多余的,那么为什么不从包名中去掉它呢?为什么不使用名称,以便您可以编写:

package STD_Code is new
   Ada.Containers.Map(Key_Type     => STD_Code_Type;
                      Element_Type => Ada.Strings.Unbounded.Unbounded_String);
Map : STD_Code.Map;

-- . . .

procedure Do_Something is
   Item : Ada.Strings.Unbounded.Unbounded_String;
begin
   Item := STD_Code.Element(STD_Code.First(Map));
   -- Do something with the Item
   -- . . .
end Do_Something;
现在
code
看起来也有点像一个没有意义的词。程序中的一切都是代码。所以我也会考虑抛弃它。毫无疑问,我将我的Ada容器包命名为表示其基本理论功能的东西(例如:
STD_to_String
),而对象是更具体的名词


另外,我应该指出,如果您的映射是常量,并且您可以使用看起来像标识符的名称,那么通常情况下,您可以通过使用枚举类型和
'image
属性完全消除字符串映射。

如果您使用ADA2012,则使用
STD_code_maps.Element(STD_code_maps.First(STD_code_map))可能会变成:

Function Get_First( Map : STD_Code_Maps.Map ) return Unbounded_String is
( STD_Code_Maps.Element(Map.First) );
这是一个新表达式函数的示例,主要针对前置和后置条件引入

当然,如果您使用的是Ada 2012,那么您可能需要的精确映射是
Ada.Containers.Indefinite\u Ordered\u Maps
——Indefinite\u*容器是那些[可以]具有不定元素的容器,如
String



除了TED的评论之外,在映射为常量时使用枚举还有更多的优点,即案例覆盖率:编译器将把任何没有覆盖所有备选方案的案例语句标记为错误。因此,如果添加新代码,它将标记所有需要修改的case语句。(当然,当您使用
其他人
案例时,此好处将丢失。)

谢谢,但这是不可能的。在我的过程中,我有一个用于向量的use子句,因为这是我使用最多的东西。矢量。光标和贴图。光标冲突。在我明确第一个(…)返回Maps包的类型Cursor之前,代码不会编译。。。不是矢量包。我必须使用STD_Code_Maps.First()让编译器明白,然后我认为重命名是最好的选择<代码>包SCM重命名STD_代码_映射应该会让生活更轻松。我想我现在就这么做吧。在学习Ada时,来自C/C++背景肯定是一个障碍。一个简单的方法就是
向量a;项目=a[0]我认为您可以理解编写
item=vector.element(vector.first(a))感觉太不对了。真是大错特错。唉。我