Ovenモドキ妄想
gcc-4.7ではAda2012のAda.Iterator_Interfacesが実装されました。
コンテナをfor文で回すためのものですが、要するに所謂"range"そのものですので、Ovenの様に連鎖させることもできるはずです。(まあこんなもの無くてもシグネチャを全部自分で決めてしまえば当然どうにでもなりますが、枠組みが標準に入ったのは大きいです)
用語の違い補足。C++のiterator=AdaのCursor、C++のrange=AdaのIterator、次の位置を求める操作はC++ではiteratorの++ですがAdaでは(Cursorではなくて)IteratorのNext関数。forward iteratorみたいな種類分けは(Cursorではなくて)Iterator側。
generic with package Source_Iterators is new Ada.Iterator_Interfaces (others => <>); package Generic_Filters is -- FilterがTrueを返したCursorのみ抽出 function Iterate ( Source : Source_Iterators.Forward_Iterator'Class; Filter : not null access function (Position : Source_Iterators.Cursor) return Boolean) return Source_Iterators.Forward_Iterator'Class; private -- 実装はこれを読んでいるあなたに任せた end Generic_Filters;
↑みたいなのを用意しておけば、↓みたいに使えるはずです。
declare package Int_Lists is new Ada.Containers.Doubly_Linked_Lists (Integer); package Int_Filters is new Generic_Filters (Int_Lists.List_Iterator_Interfaces); function Even (X : Int_Lists.Cursor) return Boolean is (Element (X) rem 2 = 0); List : Int_Lists.List; begin for I in Int_Filters.Iterate (Int_Lists.Iterate (List), Even'Access) loop Put (Element (I)); -- 偶数だけ出てくる end loop; end;
(実はGNATはgenericのformal packageのothers関係が怪しいので、このままですと通らなかったりしますがCursorとHas_Elementを個別のパラメータにしてやれば通ります。タイプ量倍増orz さっさと直らないでしょうか→ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47748)
で、まあ、こういうのってライブラリとしては面白い反面、意外と使いどころがなかったりするのですが、妄想した範囲で実用的っぽいのは、Unicodeのややこしい操作を単純化するのに使えないかなー、とかなんとか。
-- Iterate_Code_Pointsは文字列を取ってコードポイント単位のイテレータを返す関数 for I in Iterate_Code_Points (S, Substitude => ' ') loop S (I.First .. I.Last) -- slicing To_Wide_Wide_Character (I) -- code point Has_Error (I) -- TrueならUTF-*としておかしい end loop;
-- Iterate_Combiningはコードポイント単位のイテレータを取って -- Combining Character Sequence単位のイテレータを返す関数 for I in Iterate_Combining (Iterate_Code_Points (S)) loop S (I.First .. I.Last) -- slicing Compose (I) -- NFCに Decompose (I) -- NFDに end loop;
-- Iterate_Translatingはコードポイント単位のイテレータを取って -- Wide_Wide_Character_Mappingを適用する関数 for I in Iterate_Translating ( Iterate_Code_Points (S), Ada.Strings.Wide_Wide_Maps.Wide_Wide_Constant.Upper_Case_Map) loop Value (I) -- Ada.Strings.Wide_Wide_Maps.Value (Upper_Case_Map, ...) end loop;
これなら、先頭から順次NFCに変換した上でCase Foldingして比較、みたいな処理も簡単に書ける気がします。
どなたか実装しません?