Ada 202x (2日目) - parameterized array component association

というわけで、一番お気に入りの新機能から行きます。 説明を考えたら順番はgeneralized array aggregateの後の方がいいのですが、好きな順で。

経緯

配列の個々の要素を個別の値で初期化したいとします。 固定長ならそのまま書き下せばいいです。

declare
   Array_Var : array (1 .. 3) of T :=
     (1 => Create (1), 2 => Create (2), 3 => Create (3));
declare
   Geometric : constant array (0 .. 4) of Integer := (1, 2, 4, 8, 16);
declare
   Identity_Matrix : constant array (1 .. 3, 1 .. 3) of Float :=
     ((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0));

これが可変長になりますと、後から初期化するしかなかったわけです。

declare
   Array_Var : array (1 .. Length) of T;
begin
   for I in Array_Var'Range loop
      Array_Var (I) := Create (I);
   end loop;
declare
   Geometric : array (0 .. Length) of Integer;
begin
   for I in Geometric'Range loop
      Geometric (I) := 2 ** I;
   end loop;
declare
   Identity_Matrix : array (1 .. Length, 1 .. Length) of Float :=
     (others => (others => 0.0));
begin
   for I in 1 .. Length loop
      Identity_Matrix (I, I) := 1.0;
   end loop;

constant も外さざるを得ませんし、もしlimited型や task 、discriminantsを持つ型等の場合は後から初期化することができないこともあります。 taskbegin の時点で起動されてしまいます。

Ada 202xでの改善

Adam Beneschan先生の単純にして絶大な大発明。 ちなみに元Irvine Compiler Corporation所属でICC/Adaの開発者様。最近Amazonに転職されたらしい……。

まず上記例がどうなるのかを。

declare
   Array_Var : array (1 .. Length) of T :=
     (for I in 1 .. Length => Create (I));
declare
   Geometric : constant array (0 .. Length) of Integer :=
     (for I in 0 .. Length => 2 ** I);
declare
   Identity_Matrix : constant array (1 .. Length, 1 .. Length) of Float :=
     (for I in 1 .. Length => (I => 1.0, others => 0.0));

構文としてはインデックス付きaggregate式の 範囲 => の手前に for I in が挿入された形です。 そしてインデックス I を値として使うことができます。

それだけですが、それによってできるようになった事の幅がぱねぇです。 それでいて元からあった機能のように違和感もなく。 拡張はこういうふうにやるものだという見本みたいな。

関連AI

更に

こうなると内包表記に発展させたくなるのが人情で、 when でフィルターを書けるようにする提案も採択されています。 ただ配列の場合はインデックスが連続でないといけませんので、ユーザー定義コンテナ向けの機能になります。 そちらはまた後日。 (ネタを使い切らないよう小出し。)

所感

定数やlimited型の初期化は勿論、引数として配列を渡すときもインラインで書けるケースが大幅に増加したわけで、すごく嬉しい機能です。

静的型の言語で、こうやって複雑な配列定数を一発で書けるものはないのではないでしょうか。 嘘です。 Haskellのunboxed arrayが静的に展開されるならあっちが上でしょうし(されないと思ってます)、D言語のCTFEや、nimやRustのようなマクロの強力なやつならどうにでもなりそうです。 ただ無駄な過程を経ず値を組み立てられるかとなりますと、コンパイル時placement new的なものも必要になると思われますので中々難しいのでは。 挑戦しても面白いかもです。

配列の初期化式にインデックスを書くことができる他の言語としては、C言語があります。