てきとう

てきとう

Gem #3

http://www.adacore.com/2007/05/28/gem-3/

「limited typeを返すような関数が書けるよ!」

#1と#2から、limited typeにも代入できるようになったので関数が使えるようになりました。
中身の説明が興味深い。

In this case, Rumplestiltskin_Is_My_Name is allocated in the usual way (on the stack, presuming it is declared local to some subprogram). Its address is passed as an extra implicit parameter to Make_Rumplestiltskin, which then passes that same address on to Make_T, which then builds the aggregate in place at that address.

http://www.adacore.com/2007/05/28/gem-3/

適当訳: *1

この例では、 Rumplestiltskin_Is_My_Name は(サブプログラム内に宣言されていると仮定しているのでスタック上に)通常通り配置されます。そのアドレスはMake_Rumplestiltskin に暗黙のうちに追加の引数として渡され、その後同じアドレスが同様に Make_T に渡され、その後 Make_T は渡されたアドレスの指す先に aggregate を配置します。

アドレスを一々関数に渡すことで「limitedはコピーされない」ことを実現しているらしい…苦労してるんだなぁ…


この新しい機能を使えば似非単一代入で似非関数型言語っぽいことができます…?
こんな感じになる?:

type T is limited record
   N:Integer;
end record;
function Make_T(N:Integer) return T is
begin
   return (N=> N);
end Make_T;
function F(X:T) return T is
begin
   return (X.N+1);
end F;
function G(X:T) return T is
begin
   return ((F(X).N)*(F(X).N));
end G;
V: T := F(Make_T(1));
V2: T := G(V);

…うん、やらなくていいや。*2


Ada2012のExpression Functionsを使えば…!

type T is limited record
   N:Integer;
end record;
function Make_T(N:Integer) return T is (N=> N);
function F(X:T) return T is (X.N+1);
function G(X:T) return T is ((F(X).N)*(F(X).N));
V: T := F(Make_T(1));
V2: T := G(V);

わりとマシ…わりと…

*1:「配置」が気持ち悪いけど語彙が貧弱で他に思いつかない上、 aggregate は「集合」にするのが気持ち悪すぎるので放置

*2:というか試してないけどコンパイル通るんだろうか

Gem #2

http://www.adacore.com/2007/05/21/gem-2/

「aggregateで型の既定値使えるようにしたよ!」

#1の例で相変わらずZはエラーですが、Bの初期値として<>を与えることで、

X:T; -- 正しい。X.A=42, X.B='@'
Y:T := (A=>99, B=>'0'); -- 正しい。 X.A=99, X.B='0'
Z:T := (A=>64, B=> <>); -- 正しい。 X.A=64, X.B='@'

T宣言時の初期値を使うことができます。
元記事の最後に触れられている注意は、型宣言で既定値が設定されていないスカラ値は(当然)不定ということです。*1
以下のような場合Wの要素は不定です

   type U is array(1..5) of Character;
   type V is array(1..5) of S;
   W:V:=(others=> (others=> <>));

が、表記上初期化されているので単に初期化されていない場合に通常出る警告が出ません。(少なくともウチのGNAT 4.4.1では)

*1:2012でスカラも既定値の設定できるようになるらしい

Gem #1

http://www.adacore.com/2007/05/14/gem-1/

「limitedでもaggregate使えるようにしたよ!」

例えば、以下のTとX,Y,Zを考えたとき、

type T is limited record
   A:Integer:=42;
   B:Character:='@';
end record;
X:T;
Y:T:=(A=>99,B=>'0');
Z:T:=(A=>64);

Ada95では、

X:T; -- 正しい。 X.A=42, X.B='@'
Y:T:=(A=>99,B=>'0'); -- コンパイルエラー
Z:T:=(A=>64); -- コンパイルエラー

となるわけです。
しかし、Ada05ではlimited型でもaggregateで初期化できるため、

X:T; -- 正しい。 X.A=42, X.B='@'
Y:T:=(A=>99,B=>'0'); -- 正しい。 X.A=99, X.B='0'
Z:T:=(A=>64); -- コンパイルエラー

Yもコンパイルが通ります。
aggregateなので型が合えばothersでまとめて初期化ができます。

type U is limited record
   A,B:Integer;
end record;
V:U:=(others=>42);

基本的に書くコトがない

なんかネタで縛りかければ持続するかな、とか(以前の記憶から目を逸らしつつ)
というわけで1日1gem斜め読み開始。
横に読もうが縦に読もうが得られる情報に大差がないお察しな英語レベルですけど。