Silly Ada通用包裹管理?

时间:2013-08-16 08:16:52

标签: 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.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_Maps.Element(STD_Code_Maps.First(STD_Code_Map));

会更加清晰

显然我做错了 - 我想。我在那里至少重复三次STD_Code_Map这个短语。我只是为了冗长和一切,但实际上我写的代码对我来说似乎很糟糕和愚蠢。

我想知道是否有解决方案没有要求您将包重命名为package Map renames STD_Code_Maps;,这当然会缩短代码但我不想这样做这在每个程序条目上都有。我真的认为STD_Code_Map.First.Element这样的东西会简单得多。这可以在Ada 2012中完成吗?

注意:默认情况下使用Unbounded_String包也很困难。标准库设计者是否真的考虑过荒谬且过长的包层次结构?

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

5 个答案:

答案 0 :(得分:5)

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

Item := STD_Code_Map ({some Cursor});

即使使用-gnat05开关强制执行A​​da 2005模式,您也可以这样做! (这必须是一个错误)。

Ada 2005允许您使用object.function表示法调用标记类型的原始函数,前提是第一个操作数是标记类型;因此,您可以将STD_Code_Map.First写为STD_Code_Maps.First (STD_Code_Map)的简写。

将这些放在一起,你可以写

Item := STD_Code_Map (STD_Code_Map.First);

这很短!

答案 1 :(得分:4)

这个问题与泛型无关。正如Simon指出的,你可以说STD_Code_Map.First,因为STD_Code_Map的类型是标记类型,而Ada支持标记类型的这种表示法。另一方面,STD_Code_Map.First的类型是Cursor类型,它没有被标记(使得它被标记会导致声明某些同时采用Cursor和Map的操作的问题)。但即使没有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_Code_Maps.Element。 (如果需要,可以将其称为Element。重命名名称可以相同,也可以不同。)如果您经常使用该功能,这可能会有所帮助。

答案 2 :(得分:3)

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));

答案 3 :(得分:2)

让Ada中的名字变得美观可读有时会很棘手。通常情况下,语言设计师通过设计Ada标准库包以便与Ada use条款一起使用来使任务变得更糟糕,而没有考虑他们如何看待一些不能或者不想使用该功能。

在这种情况下,你可以自己做一些事情。

例如“_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看起来像是一个空意义词。程序中的 Everything 是一个代码。所以我也考虑放弃它。不合理地,我将我的Ada容器包命名为其基本理论功能(例如:STD_to_String),而对象则是更具体的名词。

另外,我应该指出,如果您的地图是常量并且您可以使用看起来像标识符的名称,通常可以使用枚举类型和'image属性完全删除地图到字符串

答案 4 :(得分:0)

如果您使用的是Ada 2012,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_Ordered_Maps - Indefinite_ *容器是[可]具有不确定元素的容器,例如String


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