Ada 2020 (49日目) - 4月29日の電子会議の結果

4月29日に行われた電子会議の議事録が公開されました。

genericの型引数のデフォルト

genericパッケージに引数を追加する場合のことを考えてみます。

generic
   type Element_Type is private;
package G1 is
   type Array_Type is array (Positive range <>) of Element_Type;
end G1;

このパッケージにいろいろ引数を追加してみます。

generic
   type Element_Type is private;
   type Index_Type is range <>;
   procedure Swap (Left, Right : in out Element_Type) is <>;
   Max_Index : Index_Type := Index_Type'Last;
package G2 is
   type Array_Type is array (Index_Type range <>) of Element_Type;
   procedure Swap (Left, Right : in out Array_Type_Type);
end G2;

サブプログラムと値に関してはデフォルトを設定できます。 この場合 Element_Type を引数に取る Swap が存在していれば実引数として明記しなくてもそれを使ってくれますし、Max_Index にしても明記しなくても Index_Type'Last が使われます。

デフォルトにより使う側の変更を抑えることができます。

しかし型にデフォルトは設定できませんでした。 従来 Positive としていたものをより一般化のために型引数 Index_Type に置き換えてしまいますと使う側も全ての箇所に実引数を足す必要がありました。

この度、型引数にもデフォルトを設定できるようになりました。 Ada 2005制定の頃から欲しがられていたやつです。 とうとう入りました。

generic
   type Element_Type is private;
   type Index_Type is range <> or use Positive;
package G3 is
   type Array_Type is array (Index_Type range <>) of Element_Type;
end G3;

これで、型引数を追加しても使う側に実引数を足さずに済むようになります。

構文は or use です。 なんでしょうね use を再利用するの流行ってるのでしょうか。

後はデフォルトを設定できないのはパッケージ引数だけです。 提案だけはされていますが Hold になってます。

未解決問題を修正しました。

制限

他の型引数に依存する型引数にデフォルトを設定することはできないようです。 この例ですと Array_Type をデフォルト付きの型引数にはできません。

type Float_Array is array (Positive range <>) of Float;

generic
   type Element_Type is private;
   type Index_Type is range <> or use Positive;
   type Array_Type is array (Index_Type range <>) of Element_Type
      or use Float_Array; -- error
package G4 is
end G4;

package I4 is new G4 (Element_Type => Float);

型引数同士の矛盾がないインスタンスが存在できたとしてもだめです。 デフォルトを通じてgenericのモデルに暗黙の条件を追加することはできません。

他の型引数に依存しなければOKです。

type Float_Array is array (Positive range <>) of Float;

generic
   type Array_Type is array (Positive range <>) of Float or use Float_Array;
package G5 is
end G5;

Ada.Numerics.Big_Numbers.Big_Integers​/Big_Reals

ちょこちょこ修正されています。 新規ライブラリですし修正自体の説明はいらないでしょう。 (手抜き)

Nonblockingの変更

17日目19日目でgenericの引数を参照する例を出しました。

このgenericの引数との論理積は常に行われるようになりましたので、わざわざ書く必要がなくなりました。 (Global アスペクトにも同様の変更が行われているらしいです?)

17日目19日目に追記してあります。

また多態呼び出し先の Nonblocking を参照するための構文 X'Nonblocking (Primitive) が追加されています。 X'Nonblocking (all) で全てのプリミティブの論理積を取れます。 (あれ? overridingNonblocking を変更することはできなかったのでは?)

Dynamic_Predicate でブロッキングを行う関数を呼びたい場合のため subtype でも Nonblocking => False を指定できるようになりました。

知らないうちの変更が多いですね。 まあ私が調べ漏らしているだけなのですが。 一度まとめ直す必要がありそうです。

Globalアスペクトの変更

Globalアスペクトにまたも変更が加えられています。

allsynchronized を指定する場合にはモードも必須になりました。

モードが書かれていないと in out の意味だったのですが、サブプログラムやgenericの仮引数等他の箇所ではモードが書かれていないと in の意味ですので一貫性を保つための変更のようです。

19日目を修正しました。

Default_Valueアスペクトと内部表現の変更

値渡しされる型は派生先でも内部表現の変更が許されています。

declare
   type S is range 0 .. 127 with Size => 8;
   type D is new S with Size => 7;

しかし Default_Value アスペクトが設定されていますと out パラメータが参照渡しのような挙動を示します。 (参照渡しそのものではなく実際は値渡し in out に近く、アドレスが渡されているわけではありません。)

理由等は面倒な話ですので割愛させていただいて、デフォルト値があると out パラメータの挙動が若干変わるとだけ把握してください。 細かいことが知りたければJohn Barnes先生の Rationale Update for Ada 2012 読んでください。この辺です。

とにかくこの挙動のせいで、元の型が Default_Value とユーザー定義のプリミティブの両方を持っている場合に派生先での内部表現の変更が禁止されていました。 正確には Default_Value の導入はAda 2012、内部表現の変更が禁止されたのはAda 2012 with Technical Corrigendum 1からですので、後から禁止されました。

Ada 2020からは再び許可されます。

declare
   type S is range 0 .. 127 with Default_Value => 1, Size => 8;
   type D is new S with Size => 7;

その他細かい修正

見落としレベルの細かい修正がひとつのAI (AI12-0373-1)に詰め込まれています。 これも詳しい説明はいいでしょう。 (手抜き)

関連AI