Ada 202x (4日目) - target name symbol ===================================== .. post:: Dec 04, 2019 :tags: ada, ada_2022 昨日の使われてなかった記号を使うようになった話の流れで残る ``@`` を先に片付けます。 適切な説明の順番? 脳内で並び替えてください。 @ - って何に使われている記号でしょうね。 メールアドレスの@はそのままatの意味です。 Adaでは ``at`` は予約語ですのでこの用法では必要ないですね。 diffではhunkを表す記号として使われています。 行位置を囲っていることからatを意図しての用法と思われます。 twitter等では宛先としてtoの意味で使われています。 (拡張された)Pascalの@はアドレス演算子です。 .. code-block:: pascal P := @X; P^ := P^ + 1 { X := X + 1 と同じ } ただ、object at addressならともかくaddress at objectの形になりますので、逆ではないかという指摘があります。 Objective-Cの@はC言語に対する拡張ワードの頭に付く記号です。 例としては ``@end`` ``@implementation`` ``@interface`` ``@protocol`` ``@selector``……他多数。 C#の@はraw stringです。 .. code-block:: csharp string s = @"\b\w+\b"; D言語、OCamlの@は属性です。 .. code-block:: d @nogc void foo(); @property int data(); .. code-block:: ocaml external ( & ) : bool -> bool -> bool = "%sequand" [@@ocaml.deprecated "Use (&&) instead."] external ( ** ) : float -> float -> float = "caml_power_float" "pow" [@@unboxed] [@@noalloc] Javaのアノテーション、JavaScriptのデコレータも、機能としてはともかく記号の使われ方としては同じようなものです。 Perlでは@は配列全体を表します。 .. code-block:: perl @array = (1, 2, 3) print($array[0]) # 1 昔のMicrosoft Basicでは@はCURRENCY型です。 固定小数点型です。 .. code-block:: basic C@ = 1234.5678 (32bit時代の?)Microsoftのstdcall呼び出し規約ではシンボルの後に引数のバイト数を続ける記号でした。 doxygen他いくつかのドキュメントジェネレーターでは特殊コマンドとして使われていることがあります。 いくつかのバージョン管理ソフトではリビジョンを表記するための記号として使われていることがあります。 makeの自動変数 ``$@`` は現在のターゲット名です。 ローグ(ローグライクゲームの元祖ローグ)では@は自分を表します。 Ada 202xでは@は --------------- 代入先への参照です。 .. code-block:: ada declare X : Float := 0.0; begin X := X + 1.0; このXに1を加える代入文は .. code-block:: ada begin X := @ + 1.0; と書き換えることができます。 記号の用途としてはmakeやローグが一番近いですね! これが言いたかっただけです! .. container:: gray-and-small これも ``[`` ``]`` と同じでpygmentsがエラーになりますね。 経緯 ---- Ada 2012でユーザー定義indexingが追加されました。 .. code-block:: ada declare package Float_Vectors is new Ada.Containers.Vectors (Positive, Float); L : Float_Vectors.Vector; begin Float_Vectors.Append (L, 0.0); といったVectorがあるとします。 これに対して .. code-block:: ada begin L (1) := L (1) + 1.0; -- error と書いてしまうと、実はエラーでした。 この文は次のように展開されます。 .. code-block:: ada begin Float_Vectors.Reference (L, 1).Element.all := Float_Vectors.Constant_Reference (L, 1).Element.all + 1.0 ``Constant_Reference`` 関数は、C++で言うところの ``const_reference operator[](size_type n) const;`` です。 ``Reference`` 関数は、C++で言うところの ``const`` の付いていない方の ``reference operator[](size_type n);`` です。 これらの関数はこのように定義されています。 | http://www.ada-auth.org/standards/2xrm/html/RM-A-18-2.html#p34.3 .. code-block:: ada function Constant_Reference (Container : aliased in Vector; Index : in Index_Type) return Constant_Reference_Type; function Reference (Container : aliased in out Vector; Index : in Index_Type) return Reference_Type; ``Constant_Reference`` の引数は ``in`` ですが ``Reference`` の引数は ``in out`` となっています。 ``Reference`` では返した参照を使って中身が変更されることに備えた追加の処理が必要になる場合があるためです。 例えば実データを参照カウンタで共有している場合にはコピーして共有を解除する必要がある等です。 そして、ひとつの文中で ``in out`` パラメータに渡したオブジェクトを同時に他に使うことはできません。 評価順によって動作が変わってしまうからです。 この例ですと ``Constant_Reference`` が先に呼ばれてしまいますと、変更前のデータに対する参照が返されます。 その後 ``Reference`` によってデータが変更されてしまいますと、``Constant_Reference`` が返した参照にアクセスすることは何らかの違反となります。 そのためこのような呼び出しはエラーです。 これは、仮に右辺も ``Reference`` の呼び出しで、``Reference`` を2回呼ぶことにしても同じです。 Ada 2012時点の解決方法としては、参照を束縛して使い回せばよいです。 .. code-block:: ada declare Ref : Float_Vectors.Reference_Type renames L (1); begin Ref := Ref + 1.0; .. container:: gray-and-small <読み飛ばし推奨> C++ではこれらのユーザー定義演算子は現在位置からのオブジェクトへのアクセス権が ``const`` かどうかで呼び分けられますが、Adaでは右辺か左辺かで呼び分けられます。 ``const`` の付いていない方は追加の処理があるかもしれませんので、できれば ``const`` の付いている方を呼ぶほうが良いです。 この点Adaの方がC++より良さそうですが、ただAdaでは ``constant`` の有無でオーバーロードができるのはこのユーザー定義indexingのみとなっています。 一般のサブプログラムではこのようなオーバーロードはできません。 C++はできます。 Ada 202xでの改善 ---------------- ``@`` を使うことで、わざわざ追加の宣言を書く必要がなくなります。 .. code-block:: ada begin L (1) := @ + 1.0 関連AI ------ - `AI12-0125-3`_ **Add @ as an abbreviation for the LHS of an assignment** - `AI12-0322-1`_ **Equivalence for the target name symbol** ボツ案の紹介 ------------ - `AI12-0125-1`_ **Add Object'Inc and 'Dec** - `AI12-0125-2`_ **Add :+, :-, :*, :/, ...** .. code-block:: ada X'Inc; X'Inc (1); X :+ 1; 単にインクリメントしたいだけならこれらの案の方が短く書けますが、ユーザー定義indexingを考えますとあらゆる用途をカバーする必要がありますので ``@`` に軍配が上がりました。 特定の演算子以外のケースにボツ案では対応できません。 .. code-block:: ada begin L (1) := Sin(@); また ``@`` は複数回用いることもできます。 .. code-block:: ada declare X : Ada.Numerics.Complex_Types.Complex := (Re => 2.0, Im => 3.0); begin X := (Re => @.Im, Im => @.Re); -- 実数部と虚数部の交換 .. role:: strike ``@`` の代わりの記号としても様々な提案がなされましたが、ベニントンで行われたミーティングの結果 ``@`` に決まったようです。 :strike:`メーリングリストによる議事録はこのように記録されているわけですが、オフラインミーティングの議事録は公開されていないようで悲しいです。` ミーティングの議事録はAIとは別に公開されています。 | http://www.ada-auth.org/arg-minutes.html 所感 ---- 風来のシレンはもう新作出ないのでしょうか。 出ても、世界樹と不思議のダンジョンの出来を見る限り期待ができそうにないのが悲しいです。 .. _`AI12-0125-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0125-1.txt .. _`AI12-0125-2`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0125-2.txt .. _`AI12-0125-3`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0125-3.txt .. _`AI12-0322-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0322-1.txt