[英]Silly Ada Generic Package Management?
我刚刚开始使用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_Maps.Element(STD_Code_Maps.First(STD_Code_Map));
显然我做错了-我认为。 我在那儿至少重复了三次STD_Code_Map。 我全都是冗长的,但我写的代码对我来说似乎很糟糕。
我想知道是否有不需要您将包重命名为package Map renames STD_Code_Maps;
类的解决package Map renames STD_Code_Maps;
这当然会缩短代码,但我不想在每个过程条目上都这样做。 我真的认为像STD_Code_Map.First.Element
这样的东西会简单得多。 可以在Ada 2012中完成吗?
注意:默认情况下使用Unbounded_String包也很困难。 标准库设计人员实际上是否对可笑和过长的包层次结构进行了很多思考?
感谢您阅读本文,并有可能帮助我。 我是Ada的新手。
GNAT GPL 2012和2013以及FSF GCC 4.7和4.8支持Ada 2012的新容器索引方案,这意味着您可以编写
Item := STD_Code_Map ({some Cursor});
即使使用-gnat05
开关强制Ada 2005模式,您也可以执行此操作! (必须是一个错误)。
Ada 2005允许您使用object.function
表示法来调用带标签类型的原始函数,前提是第一个操作数为带标签类型。 因此您可以将STD_Code_Map.First
编写为STD_Code_Maps.First (STD_Code_Map)
简写。
将它们放在一起,您可以编写
Item := STD_Code_Map (STD_Code_Map.First);
这很短!
这个问题与泛型无关。 正如Simon所指出的,您可以说STD_Code_Map。首先,由于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
。重命名名称可以相同也可以不同。)如果您经常使用该功能,则可能会有所帮助。
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));
在Ada中使名称漂亮易读有时会有些棘手。 通常,语言设计人员通过设计供Ada use
子句使用的Ada标准库程序包,使任务比原本要糟糕的多,而没有考虑他们如何看待那些不能或不想的可怜树液使用该功能。
但是,在这种情况下,您可以自己做一些事情。
例如,“ _ 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
属性来完全摆脱将地图映射为字符串的情况。
如果您使用的是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的评论外,在映射不变时使用枚举还具有更多优势,即案例覆盖:编译器会将所有未涵盖所有替代方案的案例陈述标记为错误。 因此,如果您添加新代码,它将标记您需要修改的所有案例陈述。 (当然,在使用others
案例时,这种好处会丢失。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.