简体   繁体   English

愚蠢的Ada通用套件管理?

[英]Silly Ada Generic Package Management?

I have just started using Ada, and I'm finding the generic package declarations to be rather silly. 我刚刚开始使用Ada,并且发现通用软件包声明相当愚蠢。 Maybe I'm not doing it right, so I'm looking for better options. 也许我做得不好,所以我正在寻找更好的选择。

Take a look at the below example. 看下面的例子。

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;

It would be much cleaner to simply be able to write STD_Code_Map.First.Element instead of the godforsaken STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map)); 仅仅能够编写STD_Code_Map.First.Element而不是被抛弃的STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));会更清洁STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));

Obviously I'm doing this wrong -- I think. 显然我做错了-我认为。 I'm repeating the phrase STD_Code_Map at least thrice over there. 我在那儿至少重复了三次STD_Code_Map。 I'm all for verbosity and everything, but really the code I'm writing seems bad and silly to me. 我全都是冗长的,但我写的代码对我来说似乎很糟糕。

I was wondering if there is solution that doesn't require you to rename the package to something like package Map renames STD_Code_Maps; 我想知道是否有不需要您将包重命名为package Map renames STD_Code_Maps;类的解决package Map renames STD_Code_Maps; which would of course shorten the code but I don't want to do this on each and every procedure entry. 这当然会缩短代码,但我不想在每个过程条目上都这样做。 I really think something like STD_Code_Map.First.Element would be much simpler. 我真的认为像STD_Code_Map.First.Element这样的东西会简单得多。 Can this be done in Ada 2012? 可以在Ada 2012中完成吗?

Note: Using the Unbounded_String package by default is also so difficult. 注意:默认情况下使用Unbounded_String包也很困难。 Did the standard library designers actually give much thought to the ridiculous and overly long package hierarchy? 标准库设计人员实际上是否对可笑和过长的包层次结构进行了很多思考?

Thanks for reading this, and potentially helping me out. 感谢您阅读本文,并有可能帮助我。 I'm new to Ada. 我是Ada的新手。

GNAT GPL 2012 and 2013, and FSF GCC 4.7 and 4.8, support the new container indexing scheme of Ada 2012, which means that you can write GNAT GPL 2012和2013以及FSF GCC 4.7和4.8支持Ada 2012的新容器索引方案,这意味着您可以编写

Item := STD_Code_Map ({some Cursor});

And you can do this even with the -gnat05 switch to force Ada 2005 mode! 即使使用-gnat05开关强制Ada 2005模式,您也可以执行此操作! (which has to be a bug). (必须是一个错误)。

Ada 2005 allows you to call a primitive function of a tagged type using object.function notation, provided that the first operand is of the tagged type; Ada 2005允许您使用object.function表示法来调用带标签类型的原始函数,前提是第一个操作数为带标签类型。 so you can write STD_Code_Map.First as shorthand for STD_Code_Maps.First (STD_Code_Map) . 因此您可以将STD_Code_Map.First编写为STD_Code_Maps.First (STD_Code_Map)简写。

Putting these together, you can write 将它们放在一起,您可以编写

Item := STD_Code_Map (STD_Code_Map.First);

which is quite short! 这很短!

The issue has nothing to do with generics. 这个问题与泛型无关。 As Simon pointed out, you can say STD_Code_Map.First, since the type of STD_Code_Map is a tagged type and Ada supports this notation for tagged types. 正如Simon所指出的,您可以说STD_Code_Map。首先,由于STD_Code_Map的类型是标记类型,而Ada支持标记类型的这种表示法。 On the other hand, the type of STD_Code_Map.First is a Cursor type, which isn't tagged (making it tagged would have caused problems declaring certain operations that take both a Cursor and a Map). 另一方面,STD_Code_Map.First的类型是没有标记的Cursor类型(将其标记为标记会导致声明某些同时使用Cursor和Map的操作时出现问题)。 But even without the Ada 2012 container indexing that Simon mentioned, you can say 但是,即使没有Simon提到的Ada 2012容器索引,您也可以说

STD_Code_Maps.Element(STD_Code_Map.First);

which is a little better. 更好一点。 Besides renaming a package, you can also rename the function: 除了重命名软件包,您还可以重命名该函数:

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

and you can now use just Elem instead of STD_Code_Maps.Element wherever the renaming is directly visible. 现在您可以在直接可见重命名的位置使用Elem代替STD_Code_Maps.Element (You could call it Element if you want to. The renaming name can be the same or it can be different.) This could be helpful if you use that function a lot. (如果需要,可以将其称为Element 。重命名名称可以相同也可以不同。)如果您经常使用该功能,则可能会有所帮助。

Ada was designed for readability and maintainability. Ada旨在提高可读性和可维护性。 (written once, read & maintained for much longer) This means that it does get a little verbose at times. (编写一次,读取并维护更长的时间)这意味着它确实有时会变得有些冗长。 If you prefer terse & cryptic there are plenty of other languages out there ! 如果您更喜欢简洁和神秘的语言,那么这里还有许多其他语言!

If you want to avoid typing STD_Code_Map all the time, just use a use clause: 如果要避免一直输入STD_Code_Map,请使用use子句:

use STD_Code_Map;

which would mean your code of 这意味着您的代码

   Item := STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map));

would become 会成为

   Item := Element(First(STD_Code_Map));

Getting names nice and readable in Ada can sometimes be tricky. 在Ada中使名称漂亮易读有时会有些棘手。 Often times language designers made the task worse than it had to be, by designing Ada standard library packages for use with Ada use clauses, without a thought to how they'd look to some poor sap who either can't or doesn't want to use that feature. 通常,语言设计人员通过设计供Ada use子句使用的Ada标准库程序包,使任务比原本要糟糕的多,而没有考虑他们如何看待那些不能或不想的可怜树液使用该功能。

In this case though, there are things you can do on your own end. 但是,在这种情况下,您可以自己做一些事情。

For example "_Maps.Map" is redundant, so why not get rid of it from the package name? 例如,“ _ Maps.Map”是多余的,那么为什么不从程序包名称中删除它呢? Why not use names so that you can write: 为什么不使用名称来写:

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;

Now Code looks like a bit of a null-meaning word too. 现在, Code看起来也像是一个零含义的单词。 Everything in a program is a code. 程序中的所有内容都是代码。 So I'd consider ditching it as well. 所以我也考虑放弃它。 Unsually I name my Ada container packages something that says their basic theoretical function (eg: STD_to_String ), while objects are more specific nouns. 没想到我给Ada容器包装了一些名称,这些名称说明了它们的基本理论功能(例如: STD_to_String ),而对象是更具体的名词。

Also, I should point out that if your map is constant and you can live with names that look like identifiers, often times you can get rid of maps to strings entirely by using an enumerated type and the 'image attribute. 另外,我要指出的是,如果您的地图是恒定的,并且您可以使用看起来像标识符的名称,那么通常您可以使用枚举类型和'image属性来完全摆脱将地图映射为字符串的情况。

If you're using Ada 2012 the STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map)); 如果您使用的是Ada 2012,则STD_Code_Maps.Element(STD_Code_Maps.First(STD_Code_Map)); could become: 可能成为:

Function Get_First( Map : STD_Code_Maps.Map ) return Unbounded_String is
( STD_Code_Maps.Element(Map.First) );

That is an example of the new Expression-functions, which were mainly introduced for pre- and post-conditions. 这是新的表达式函数的一个示例,主要针对前置条件和后置条件引入。

Of course, if you're using Ada 2012 then the precise map you'd likely want is Ada.Containers.Indefinite_Ordered_Maps -- the Indefinite_* containers are those that [can] have indefinite elements, like String . 当然,如果您使用的是Ada 2012,那么您可能想要的精确地图是Ada.Containers.Indefinite_Ordered_Maps -Indefinite_ *容器是[可以]具有不确定元素的容器,例如String


In addition to TED's comment, using an enumeration when the maps are constant have even more advantages, namely case coverage: the compiler will flag as an error any case-statement that doesn't cover all alternatives. 除了TED的评论外,在映射不变时使用枚举还具有更多优势,即案例覆盖:编译器会将所有未涵盖所有替代方案的案例陈述标记为错误。 So if you add a new code it will flag all the case-statements that you need to modify. 因此,如果您添加新代码,它将标记您需要修改的所有案例陈述。 (Of course this benefit is lost when you use the others case.) (当然,在使用others案例时,这种好处会丢失。)

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

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