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して比較、みたいな処理も簡単に書ける気がします。

どなたか実装しません?