Ada 202x (8日目) - iterator filter¶
順調に投稿時刻が後にずれていっております。 なお毎日のリハビリですので書き溜めはしないようにしております。
これまでのあらすじ¶
Adam Beneschan先生の提案parameterized array component associationはわずかな変更でAdaという言語に大きな影響を与えました。
刺激を受けたTucker Taft先生がaggregate式をもっと発展させようとした結果、どんどん内包表記っぽいことになっております。
Ada 202xでのiterator filter¶
for
ループとaggregate式中のparameterized array component associationに when
で条件を書くことができます。
条件を満たさない試行は飛ばされます。
先に例で用いるユーザー定義コンテナを宣言しておきます。
declare
package Integer_Sets is
new Ada.Containers.Ordered_Sets (Integer);
S : constant Integer_Sets.Set := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for文の場合。 偶数のみ出力します。
begin
for I in S.Iterate when S (I) rem 2 = 0 loop
Put (S (I));
end loop;
勿論 in
ではなく of
形式でもフィルタは使えます。
of
はAda 2012からの形式で、復習しますと in
はインデックス(Cursor
、C++で言うイテレータ)をパラメータとするループで of
は値そのものをパラメータとして受け取るループです。
begin
for E of S when E rem 2 = 0 loop
Put (E);
end loop;
aggregate式の場合。
declare
X : Integer_Sets.Set := [for E of S => when E rem 2 = 0];
X
には偶数のみが格納されます。
このようにparameterized array component associationでも of
は使えます。
これも配列のときに説明しそびれました。
in
はnamed association 、 of
はpositional associationに対応します。
この例ですと Ada.Containers.Ordered_Sets
はnamed associationをサポートしていませんので in
で書くことはできません。
Ada.Containers.Ordered_Maps
であればキーと値のペアによるnamed associationをサポートしていますので in
で書くことができます。
declare
package Integer_Maps is
new Ada.Containers.Ordered_Maps (Integer, Integer);
Y : constant Integer_Maps.Map :=
[for I in S.Iterate when S (I) rem 2 = 0 use S (I) => S (I) + 1];
Y
は [2 => 3, 4 => 5, 6 => 7, 8 => 9, 10 => 11]
となります。
この短い式で Set
から Map
へ中身を移せたことにも注目です。
内包表記がマップ関数とフィルタ関数を兼ねることができるのと、同じことができています。
以前インデックスが連続である必要があるため配列ではフィルタは使えません、と書きましたが、補足しておきますとループする対象としては配列は使用できます。
フィルタが使えないのは配列を出力先の型とする場合です。
(違っているかもしれません。もしかしたら others =>
で抜け番を補えば配列でも使えるかもしれません。)
そのため配列からユーザー定義コンテナにマップする場合はフィルタも使えます。
for文でも常に使えます。
begin
for I in 1 .. 10 when rem 2 = 0 loop
Put (I);
end loop;
まあでも上の例もそうですがfor文の場合は続けてif文を書く場合に比べてインデントを1段省略できる程度の意味しかありません。
begin
for I in 1 .. 10 loop
if I rem 2 = 0 then
Put (I);
end if;
end loop;
aggregate式で使ってこその機能です。
組み合わせ例¶
説明しそびれていたこともありましたので、ここまで紹介した機能を組み合わせた例を挙げておきます。
positional association。
[for E of C => Map (E)]
positional association。フィルタ付き。
[for E of C when Filter (E) => Map (E)]
named association。インデックスはそのまま。
[for I in C.Iterate => Map (I)]
named association。インデックスはそのまま。フィルタ付き。
[for I in C.Iterate when Filter (I) => Map (I)]
named association。インデックスも変更。
[for I in C.Iterate use To (I) => Map (I)]
named association。インデックスも変更。フィルタ付き。
[for I in C.Iterate when Filter (I) use To (I) => Map (I)]
関連AI¶
AI12-0250-1 Iterator Filters
AI12-0327-1 Clarify iterator filter wording for aggregates