Ada 2020 (14日目) - Unify record syntax

タイトルはAda 2012 Issues(以降AI)のまんまです。

経緯

他の構文と異なり recordend の後に名前を書けませんでした。

type Rec is record
   E : Integer;
end record; -- ここに "Rec" と書けませんでした

Ada 2020での改善

書けるようになりました。

type Rec is record
   E : Integer;
end record Rec;

関連AI

所感

このAI、提出者がJustin Squirekさんです。 (発案はTucker先生のようです。) Justinさんはgithubの https://github.com/AdaDoom3/ さんです。 数年前にAdaCore社に就職されたと聞いております。 感慨深く。

どうインデントすればいいのか?

めでたしめでたし、で済ませたいのです。 はい、例によって書いておきたいことが。 機能ではなくコーディングスタイル、ただの長い行の折り返し方の話、かつ100%私見ですので読むだけ損です。

正直私にはJean Ichbiah先生率いる初代Ada 83を策定したチームがこんなのを見逃したとは思えないわけですよ。 裏付けはありませんが record に名前を続けられないのはわざとそうしていたのではと推測しています。

他にAda 83から存在する end の後に名前を続けられる構文を見てみましょう。

パッケージ。

package Pack1 is
   -- declarations
end Pack1;

サブプログラム。procedurefunctionentry

procedure Proc1 is
   -- declarations
begin
   null;
end Proc1;

task

task Task1 is
   -- declarations
end Task1;
task type Task1 is
   -- declarations
end Task1;
task body Task1 is
   -- declarations
begin
   null;
end Task1;

ブロック文。

Label:
   begin
      null;
   end Label;
Label:
   declare
      -- declarations
   begin
      null;
   end Label;

ループ文。

Label:
   loop
      null;
   end loop Label;

accept文。

accept Entry1 do -- 新規宣言ではなく既存のentry名
   null;
end Entry1;

以上です。 そして record の「本来の」インデントはこうです。

type Rec is
   record
      E : Integer;
   end record;

他にはAda 95からの protectedend の後に名前を続けられます。 Ada 2005からの拡張return文は識別子の宣言を伴いますが end の後に名前は続けられません。

基本的に先頭行と end の行が揃うようになっています。 例外はブロック文、ループ文、record で本体が名前よりも一段深くインデントされます。 (Rationaleを見ますとループ文と record が例外なのは認識されています。)

このうち宣言文なのは record のみです。

task type 同様に record type のような文法でしたら end の行を先頭行に揃えるべきでしょう。 そうなっていないという事は record は他の型宣言同様に is 以降でひと塊と考えるべきです。 そう考えると本体を一段深くするインデントルールも納得できますし end に名前を続けないのも理解できます。

このインデントルールはAda 95以降の tagged record やインターフェースを継承するために長くなった宣言にも良く合致します。

type Rec_Having_Long_Declaration is
  abstract new Ada.Finalization.Limited_Controlled
    and Ada.Iterator_Interfaces.Forwared_Iterator with
       record
          E : Integer;
       end record;

或いは is から with までをAda 2005以降の protected がインターフェースを継承する場合の構文に倣うことも考えられます。

protected Long_Long_Protected_Name is
  new Long_Long_Package_Name.Long_Long_Interface_Name_1
    and Long_Long_Package_Name.Long_Long_Interface_Name_2 with
   -- declarations
end Long_Long_Protected_Name;

この with は継承の終わりかつ宣言の開始を意味する区切りで tagged record を継承する用法に近いです。 個人的には区切りを明確にするために(procedure の引数リストが長くなった後の is 同様に)この with の前で改行したくなりますが、しないのが主流っぽいです? (protected の継承だけでもマイナーなのに改行するほど長くなった例なんて更に少ないのでよくわかりません。)

要は with を区切りに継承部分のインデントを後に影響させないということです。 record を一段だけインデントするのは前提としますとこうでしょうか。

type Rec_Having_Long_Declaration is
  abstract new Ada.Finalization.Limited_Controlled
    and Ada.Iterator_Interfaces.Forwared_Iterator with
   record
      E : Integer;
   end record;

何れにせよこのインデントされた end の後ろに名前を続けるのって変じゃないですか? しかもAda 2012以降はアスペクトを追加すると end が最終行ですらなくなります。

type Rec_Having_Long_Declaration is
  abstract new Ada.Finalization.Limited_Controlled
    and Ada.Iterator_Interfaces.Forwared_Iterator with
   record
      E : Integer;
   end record Rec_Having_Long_Declaration -- 次の行に続く
     with Pack; -- アスペクト

これを end 行を先頭行に揃えようとしますとこうなってしまいます。

type Rec_Having_Long_Declaration is
  abstract new Ada.Finalization.Limited_Controlled
    and Ada.Iterator_Interfaces.Forwared_Iterator with
record
   E : Integer;
end record Rec_Having_Long_Declaration
  with Pack;

またはアスペクトに合わせて with の前で折り返しますと

type Rec_Having_Long_Declaration is
  abstract new Ada.Finalization.Limited_Controlled
    and Ada.Iterator_Interfaces.Forwared_Iterator
with record
   E : Integer;
end record Rec_Having_Long_Declaration
  with Pack;

うーん?

と、まあ、このようなことを書いて悩むふりをしつつ実は私は元から end を先頭行に揃える派なのですけどね。 宣言の長さで要素のインデントが左右されませんので。 コーディングスタイル違反を自覚していたのですが、まさか間接的に正当化されるとはびっくりです。 (されてないされてない。)

ちなみにGNATのソースには様々なスタイルが混じってたりします。

それでも私は今更 end record の後に名前を書き足したりはしないとは思います。 恐らく誰も書かないのではないでしょうか。 やっぱり今更ですよ。

Pascal系言語は他ほどインデントに迷わないのも利点と思っています。 この変更は迷うポイントを追加する変更であることは間違いありません。