Ada 202x (2日目) - parameterized array component association ============================================================ .. post:: Dec 02, 2019 :tags: ada, ada_2022 というわけで、一番お気に入りの新機能から行きます。 説明を考えたら順番はgeneralized array aggregateの後の方がいいのですが、好きな順で。 経緯 ---- 配列の個々の要素を個別の値で初期化したいとします。 固定長ならそのまま書き下せばいいです。 .. code-block:: ada declare Array_Var : array (1 .. 3) of T := (1 => Create (1), 2 => Create (2), 3 => Create (3)); .. code-block:: ada declare Geometric : constant array (0 .. 4) of Integer := (1, 2, 4, 8, 16); .. code-block:: ada 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)); これが可変長になりますと、後から初期化するしかなかったわけです。 .. code-block:: ada declare Array_Var : array (1 .. Length) of T; begin for I in Array_Var'Range loop Array_Var (I) := Create (I); end loop; .. code-block:: ada declare Geometric : array (0 .. Length) of Integer; begin for I in Geometric'Range loop Geometric (I) := 2 ** I; end loop; .. code-block:: ada 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を持つ型等の場合は後から初期化することができないこともあります。 ``task`` は ``begin`` の時点で起動されてしまいます。 Ada 202xでの改善 ---------------- Adam Beneschan先生の単純にして絶大な大発明。 ちなみに元Irvine Compiler Corporation所属でICC/Adaの開発者様。最近Amazonに転職されたらしい……。 まず上記例がどうなるのかを。 .. code-block:: ada declare Array_Var : array (1 .. Length) of T := (for I in 1 .. Length => Create (I)); .. code-block:: ada declare Geometric : constant array (0 .. Length) of Integer := (for I in 0 .. Length => 2 ** I); .. code-block:: ada 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 ------ - `AI12-0061-1`_ **Index parameters in array aggregates** 更に ---- こうなると内包表記に発展させたくなるのが人情で、 ``when`` でフィルターを書けるようにする提案も採択されています。 ただ配列の場合はインデックスが連続でないといけませんので、ユーザー定義コンテナ向けの機能になります。 そちらはまた後日。 (ネタを使い切らないよう小出し。) 所感 ---- 定数やlimited型の初期化は勿論、引数として配列を渡すときもインラインで書けるケースが大幅に増加したわけで、すごく嬉しい機能です。 静的型の言語で、こうやって複雑な配列定数を一発で書けるものはないのではないでしょうか。 嘘です。 Haskellのunboxed arrayが静的に展開されるならあっちが上でしょうし(されないと思ってます)、D言語のCTFEや、nimやRustのようなマクロの強力なやつならどうにでもなりそうです。 ただ無駄な過程を経ず値を組み立てられるかとなりますと、コンパイル時placement new的なものも必要になると思われますので中々難しいのでは。 挑戦しても面白いかもです。 配列の初期化式にインデックスを書くことができる他の言語としては、C言語があります。 .. _`AI12-0061-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0061-1.txt