簡體   English   中英

愚蠢的Ada通用套件管理?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM