日本ソフトウェア科学会第 30 回大会 (2013 年度) 講演論文集

Method と Event、Advice、および Behavior を統合する言語機構
莊 永裕

千葉 滋

本稿では複数のプログラミングパラダイムの実装に使える汎用的な言語機構 method slot を提案する。Methodslot は field のようなオブジェクトの属性であり、実体は closure の配列である。Method slot はアスペクトパラダイムの advice として使えるだけでなく、イベントハンドラパラダイムの event と handler としても使える。また、
method slot の中で使っている field はリアクティブパラダイムの behavior のように常に最新の値を保つことが可能である。本稿では、さらに Java を拡張して method slot を利用可能にした DominoJ という言語を紹介する。

In order to simplify the constructs used for multiple programming paradigms such as the aspect paradigm,
the event-handler paradigm, and the reactive paradigm, we propose a new language construct named method
slots. A method slot is an object’s property like a field, which is an array of function closures. Method
slots can be used as methods, events, and advices. Furthermore, the fields used in a method slot can work
as behaviors. We also propose a Java-based language supporting method slots, DominoJ, to show concrete
examples.

バーパターン [5] を改良したものといえ、それを支援

1 はじめにする多数のライブラリが存在する [14] [13]。近年では、

良いプログラムを書くためには、プログラミングパイベントハンドラパラダイムを言語機構として支援ラダイムを応用することが重要である。しかし、プロする研究も多数行われている [6] [4] [12]。また、ファン

グラマはパラダイムの概念だけではなく、そのパラダクショナル・リアクティブ・プログラミング（以下、イムを実現するための言語機構も学ばなければならリアクティブパラダイム） [3] [11] を、オブジェクト指ない。その原因は、各パラダイムのための言語機構は向言語に対して適用する研究もある [9]。これらの研往々にしてそのパラダイムに専用であるためである。

究は数々の新しい言語機構を生み出している。それらあるパラダイムの言語機構の使い方に慣れても、ほかを全て習得するのは容易ではない。のパラダイムにはその経験を流用できない。そのパラ一方、オブジェクト指向言語の method は汎用的ダイムで書いたコードも再利用しにくい。例えば、アな言語機構である。アスペクトパラダイムやイベンスペクト指向プログラミング（以下、アスペクトパラトハンドラパラダイムの一つの要素として使われる。

ダイム）を用いると、横断的関心事を分離することがしかし、method には不十分なことも多い。例えば、可能になる [7]。しかし、AspectJ のような強力な言語そのままでは event や advice として使えない。多く

は、提供する専用の言語機構が多く、その使い方に慣のパラダイムに一つで対応できる言語機構を提供すれるのは容易ではない。イベント駆動型プログラミンることで、プログラミング言語をより簡潔なものにグ（以下、イベントハンドラパラダイム）はオブザーするため、我々は method を拡張した新しい言語機

Integration of methods, events, advices, and behaviors
YungYu Zhuang
Shigeru Chiba, 東京大学情報理工学系研究科創造情報学専攻, Dept. of Creative Informatics, Grad. School of Information Science andTechnology, The University of Tokyo..

構 method slot を提案・実装してきた [16] [15]。本稿
では method slot の概要を述べるとともに、特にアスペクトパラダイムと method slot との関係について議論する。Method slot とアスペクトパラダイムとの関係は [16] で議論したが、 [15] の中で追加された機能を含めた議論はまだであるので、本稿はそれを中心に述べる。また method slot を使ったプログラミング

リスト 1
1

AspectJ で和を自動的に計算する例

public class Num {2private int x = 0; private int y = 0;3

public void setX(int nx) { this.x = nx; }DominoJ とそのリアクティブ拡張 ReactiveDominoJ4

public void setY(int ny) { this.y = ny; }（以下、DominoJ）についても紹介する。

5

public void calc() {を実証的に議論するために開発した Java の拡張言語

6

int sum = this.x + this.y;72 問題意識
より良いプログラムを書くため、プログラマは常System.out.println(sum);

8}

9}

10

public aspect Glue {にプログラミングパラダイムを学習しなければなら11ない。例えば、横断的関心事をモジュールとして分

12after(Num n) returning:(execution(void Num.setX(int))

13|| execution(void Num.setY(int)))

離できるアスペクトパラダイムやモジュールの疎結

14&& target(n) {合を実現するイベントハンドラパラダイム、データ

15

フローのような数値の変化を自動的に伝播するリア

n.calc();1617}}

クティブパラダイム。この三つのパラダイムはそれぞれの問題を解くために考案されたが、実装に共通点がある。それは指定された「コード」を指定されリスト 2た「時点」に自動的に実行することである。アスペクトパラダイムでは、advice が実行させたい「コー1EScala で和を自動的に計算する例

class Num() {2var x = 0; var y = 0

ド」で、pointcut で選択した join point が実行させ3def setX(nx: Int) { this.x = nx }たい「時点」である。イベントハンドラパラダイム

4def setY(ny: Int) { this.y = ny }5def calc() {も、event の値の「時点」で指定された「コード」、つ6var sum = this.x + this.y

まり handler が自動的に呼び出される。リアクティブ

7パラダイムはある behavior の値が変化した時に、そ8}9evt changed[Unit] = afterExec(setX)の behavior を使っている文が再評価される。文は一10番短い「コード」と考えられる。つまり、リアクティ

11ブパラダイムにとって、実行させたい「時点」はそ12println(sum)|| afterExec(setY)changed += calc}の behavior の値が変化する時であり、実行させたい「コード」はその behavior を使っている文である。

リアクティブパラダイムの実装である。8 行目と 9 行

ここで二つの変数 x と y の和を求める例で説明す目では名前が X と Y の DOM 要素から値をそれぞれる。リスト 1 はアスペクト指向言語 AspectJ で書い抽出する behavior を変数 x と y に代入している。そた例である。変数 x と y の和の計算はクラス Num のして x と y の和 sum を計算して（10 行目）、名前が中に定義されている。毎回 x や y に新しい値が与え

SUM の DOM 要素にその結果を与える（11 行目）。

られた後に、sum を自動的に更新する。このようなこの三つのパラダイムは解決する問題は違うが、実プログラムはイベントハンドラパラダイムとリアク

装上の言語機構には似ている部分がある。Method のティブパラダイムでも書ける。リスト 2 とリスト 3

呼び出しや field の変化を「時点」にする、そしてあはそれぞれ EScala [6]、Flapjax [9] で書いた例である「コード」をこの「時点」の対処として、その「時る。EScala は Scala を拡張した言語で、6-7 行目の点」で自動的に実行する。

ような event 宣言と 8 行目の handler 指定をするこ

残念ながら、既存の言語機構はこの三つのパラダイとが可能になる。一方、Flapjax は JavaScript 上のムを同時に支援することはできない。つまり、既存のŽďũĞĐƚƐ͗ĐůĂƐƐ ^ŚĂƉĞ

リスト 31

Flapjax で和を自動的に計算する例<body onload="loader()">2<input id="X"

size=2 value="0" />3<input id="Y"

size=2 value="0" />4<input id="SUM" size=2 value="0" readonly />5ŝŶƚ ǆĨƵŶĐƚŝŽŶ ƐĞƚyvoid (int nx) -> { this.x = nx; }| this = s</body>6<script type="text/javascript">

7function loader() {8var x = extractValueB("X");9

var y = extractValueB("Y");10

var sum = x + y;11

insertValueB(sum, "SUM", "value");

12}

13</script>

図1

JavaScript には integer も function も field

としてオブジェクトに保存される（ [16] より引用）ŽďũĞĐƚƐ͗ĐůĂƐƐ ^ŚĂƉĞŝŶƚ ǆŵĞƚŚŽĚƐůŽƚ ƐĞƚyvoid (int nx) -> { target.update(nx); }| target = ovoid (int nx) -> { this.x = nx; }| this = s

言語機構はそれぞれのパラダイムの専用機構で、他のパラダイムの実装には使えない。あるパラダイムを使

図2

Method slot は拡張した field で、複数のfunction を持つことができる（ [16] より引用）

いたいときはそのための専用機構の使い方を覚えなければならない。しかし、AspectJ のような強力な言

3. 1 Method slots

語に慣れることは容易ではない。更に、パラダイムとField と method は、C++や Java のような言語でその言語機構は往々にして特定のプログラミング言語は異なる機構であるが、JavaScript のようなそれらでのみ支援されるため、同時に複数のパラダイムを使を区別しない言語もある。JavaScript では method

うことができない。仮に全ての言語機構を一つのプ（より正確に言えば function closure）も一つの field

ログラミング言語で支援することができたとしても、に保存されたオブジェクトである。例えば、図 1 のそれら全ての言語機構の使い方に慣れることが必要

x は整数値を持つ field だが、setX も closure を持つである。言語機構の間の書き換えも複雑であるため、field である。s.setX を呼び出すと、与えられた引数

プログラマは最初から使いたいパラダイムを決めなでその closure を実行する。Method slot はこのようければならない。このように、複数のパラダイムを使な field を拡張して、二つ以上の closure を持つことい分けるには困難が伴い、我々がより汎用的な言語機を可能にしたものである。つまり、method slot はオ構を考案する動機となった。

ブジェクトの属性で、closure の配列である。図 2 のsetX は method slot で、二つの closure を持ってい3 DominoJる。Method slot を呼び出すと、与えられた引数で全アスペクトパラダイムとイベントハンドラパラダての closure が順番に実行され、最後の closure の戻イムとリアクティブパラダイムを一つの言語機構で支り値がこの method slot の戻り値として返される。

援するため、我々は method slot という言語機構をDominoJ は Java の method を method slot に置提案する。Method slot は汎用的な言語機構で、オブき換えた言語である。つまり、DominoJ では全てのジェクト指向の method パラダイムと、前述の三つmethod 宣言は method slot 宣言と見なされる。例えのパラダイムの言語機構の実現に使える。以下では、

ば、次のような class 宣言の中の setX 宣言は method

method slot が利用可能なように拡張された Java 言宣言ではなく、method slot 宣言である。

語である DominoJ 言語を用いて説明する。

public class Shape {
private int x;
public void setX(int nx) { this.x = nx; } }この setX 宣言は、戻り値の型が void、パラメーターの型が (int) の method slot を宣言する。また、setX

リスト 4
1

宣言の後ろの波括弧の中、method body のような宣DominoJ によるイベントハンドラパラダイム

public class Num {2private int x = 0; private int y = 0;3

public void setX(int nx) { this.x = nx; }ある。Default closure はオブジェクト生成時にはじ

4public void setY(int ny) { this.y = ny; }めから method slot に入ってる closure であり、次の5

public void calc(int v) {言は、この method slot の default closure の宣言で6int sum = this.x + this.y;ように表現できる。

7void (int nx) -> { this.x = nx; }8}9public Num() {| this = sSystem.out.println(sum);10

this.setX += this.calc;

113. 2 Method slot の演算子とイベントハンドラ

this.setY += this.calc;

1213}
}

パラダイムとリアクティブパラダイムの実装

DominoJ 言語は、method slot を扱う四つの二項演算子と一つの単項演算子†1 を提供する。演算子+=は、

public void calc(int v);

右辺の method slot を呼び出す closure を作って、左演算子^=は演算子+=とは異なり、配列の先頭に clo-辺の method slot（closure 配列）最後尾に追加する。

sure を作って追加する。演算子=も左辺の method slot

例えば、リスト 4 の 10 行目は、method slot であるに closure を追加するが、追加する前にその配列を空

this.calc を呼び出す closure を作って、method slotにする。一方、演算子-=は、左辺の method slot のである this.setX に追加する。注意する点は setX と配列から、右辺の method slot を呼び出す closure をcalc の型（戻り値の型とパラメーターの型）は一致し全て削除する。

なければならないことである。calc を呼び出すときは単項演算子{}は、まず与えられた method slot でsetX に渡す引数をそのまま calc に渡すので、ここで参照されている全ての field を求める。次にその field引数を指定する必要はない。演算子+=は C#の eventの値を書き換える method slot の集合を返す。例えの演算子+=と同じ意味である。演算子左辺の method

ば、リスト 5 の 10 行目の{this.calc}は、setX と setY

slot は event で、右辺の method slot は handler とを返す。つまり、この文はリスト 4 の 10-11 行目と同見なせる。つまり、イベントハンドラパラダイムのじ意味である。{this.calc}は、calc の default closure

視点でこの例を考えると、setX の宣言は event の宣が参照している field は x または y であり、それらの言である。その default closure は、予め用意される値を書き換える method slot を選択する。DominoJhandler である。また、calc はその次に実行させるのコンパイラは calc の default closure の中から呼びhandler である。setX という event が発生すると、出される method slot についても同様に、field の値

setX の default closure と calc は順番に実行される。

を書き換える method slot を再帰的に探す。例えば、

これはリスト 2 に使われている EScala の afterExec

もし calc が次のように定義されるならば、{this.calc}と+=の組み合わせに対応する。
演算子+=を使い、event の合成もできる。例えば、
リスト 4 の 10-11 行目では、calc を setX または setYは field z を書き換える method slot、つまり setZ も選択する。

public void calc() {によって発生させられる event にしている。もし calc

int sum = this.x + this.y + this.getZ();の宣言を下のように変え、default closure を定義しSystem.out.println(sum);

ないと、一般的な higher-level event と同じになる。

}
public int getZ() { return this.z; }†1 リアクティブ拡張 ReactiveDominoJ で提供する

public void setZ(int nz) { this.z = nz; }リスト 5
1

DominoJ によるリアクティブパラダイム

public class Num {

リスト 6
1

DominoJ によるアスペクトパラダイム

public class Num {2private int x = 0; private int y = 0;2

private int x = 0; private int y = 0;3

public void setX(int nx) { this.x = nx; }3public void setX(int nx) { this.x = nx; }4public void setY(int ny) { this.y = ny; }4public void setY(int ny) { this.y = ny; }5public void calc() {5public void calc(int v) {6int sum = this.x + this.y;6

7System.out.println(sum);78}

9public Num() {1012System.out.println(sum);8{this.calc} += this.calc();

11int sum = this.x + this.y;}
}

}

9}

10public class Glue {11public static void init() {12Num n = ((Num)$predecessor);

13n.setX += n.calc;

14演算子{}は左辺式でしか使えない。また、演算子{}の右辺の method slot には引数を明示的に指定しなn.setY += n.calc;15}

1617

static { Num.constructor += Glue.init; }}ければならない。
リスト 5 のようにすると、calc の中で使われている x と y は、リアクティブパラダイムの behavior となければ、普通の Java の method と同じである。ま同じ意味となる。x と y を使っているコードは、x やた、演算子+=を使って、指定される method slot を、y の値が変化する時に、自動的に再実行される。すな

ほかの method slot の default closure を実行した後

わち、calc の中の x と y は常に最新の値を保つ。たに、呼び出すことが可能であるので、after advice をだし、リアクティブパラダイムと違い、プログラマがmethod slot で実現できる。例えば、リスト 1 の Glue

明示的に演算子{}で、behavior の有効範囲を指定しaspect は、リスト 6 の Glue class に書き換えられる。

なければならない。この例では、calc 以外のコード中

なお、AspectJ のような pertarget のような aspect ので使われている x と y は behavior とは言えない。な

インスタンス管理機構を提供しないので、DominoJ

ぜなら、それらのコードは x や y の値が変化してもでは自分でオブジェクトを生成しなければならない。

自動的に再実行されないからである。

リスト 6 の 16 行目で class 名の後ろに付いている
キーワード constructor は、object creation pointcut

3. 3 アスペクトパラダイムの実装のようなもので、演算子の左辺式だけで使える。

アスペクトパラダイムのための言語は、横断的関

AspectJ の advice には、before や after、around

心事を分離するため、join point を選択する宣言と、の区別があるが、DominoJ には直接それに対応する機その時実行するコード、そのコードを集めるモジュー構はない。しかし、before、after、around と同等のもルを提供しなければならない。AspectJ では Java ののを実現する表現力はある。演算子^=、+=、=のそれぞclass と method に加え、aspect と advice、pointcut

れを使って、演算子の左辺の method slot が実行されと呼ばれる言語機構を導入して、これを実現していた時に、右辺の method slot を before/after/aroundる。AspectJ は before と after と around 三種類のadvice として、呼び出すように工夫できる。例えば、advice を提供する。

リスト 6 の 13 と 14 行目は n.calc を after advice とDominoJ は、method slot で method と advice を統合する。Aspect は class として書ける。Method

して、それぞれ n.setX と n.setY が呼び出された直後に実行されるようにしている。

slot は拡張した method と言える。まず宣言に de-

DominoJ の演算子^=、+=、=は、AspectJ の exe-fault closure をつけて、method slot の演算子を使わcution pointcut と見なせる。ただし、DominoJ は

AspectJ の within のような複雑な pointcut を提供しgetX の default closure も printX の default closureないので、call pointcut と execution pointcut の違も x しか読まないので、左辺を次のように{s.printX}いは表現できない。一方、AspectJ の target pointcutで書き換えても同じ意味である。

はリスト 6 の 12 行目のようにキーワード$predecessor{s.printX} += s.printX;で提供される。

この意味は、s.printX の実行結果に影響する全てのDominoJ では AspectJ の field pointcut、つまりfield の値が変わったら、s.printX を自動的に再実行

get pointcut と set pointcut を、演算子{}と accessorするということである。Class の中のプライベートのmethod で実現できる。例えば、次のようなコードをfield を意識しなくてもその値の変化を捉えることが考える：できる。

public class Shape {
private int x;

4 関連研究public void setX(int nx) { this.x = nx; }既存の言語にはオブジェクト指向言語に加え、他

public int getX() { return this.x; }のパラダイムのための言語機構を提供するものがあ

private void reset() { this.x = 0; }る。しかしながら、一つの言語機構で複数のパラダ

public void printX() {イムに対応するものは我々の知る限りない。例えば、

System.out.println(this.x);

C# [10] はイベントハンドラパラダイムを提供するが、event 宣言は method とは異なる。AspectJ のほ}}か、アスペクトパラダイムを支援する言語もいくつ

AspectJ ではこの x に対するアクセスを次のようなか存在する [1] [2] が、method とは異なる言語機構でfield pointcut で捉えることができる。

実現している。また、Scala や JavaScript ではリア

public aspect Glue {クティブパラダイムをライブラリで実現できる [9] [8]after(Shape s) returning:set(int Shape.x) && target(s) {が、リスト 3 で示したように、behavior と value を明示的に変換する必要がある。

s.printX();
}
}

5 まとめ
本稿は method を拡張した method slot を提案し、この例のような x の書き込みを捉えることは、call

一つの言語機構でアスペクトパラダイムとイベントpointcut だけどはできない。何故ならば、accessor

ハンドラパラダイム、リアクティブパラダイムを支援

method はその field を隠蔽して class 外部から呼びする方法を述べた。特に method slot によるアスペ出されるためのものであり、基本的に class 内部でクトパラダイムの実装方法について議論した。今後のは呼び出されず、class 内部での field へのアクセス課題としては、既存の言語で実装されたこの三つのパを捉えられないからである。我々は、DominoJ をよ

ラダイムのコードの典型例を、DominoJ のコードとり簡潔なものにするため、field pointcut を直接的に比較することである。また、DominoJ でほかのパラ提供しないが、演算子{}で field を書き換える全てのダイムを支援することについても考えたい。

method slot を得ることができ、演算子^=や+=や=と組み合わせることで、その field を書き込まれた時に参 考 文 献実行する advice を表現できる。例えば、次の例は s.x[ 1 ] Aracic, I., Gasiunas, V., Mezini, M., and Ostermann, K.: An Overview of CaesarJ, Transactions on Aspect-Oriented Software Development
I, Lecture Notes in Computer Science, Vol. 3880,Springer, 2006, pp. 135–173.の値が変わる時に s.printX を呼び出す（オブジェクトs は Shape のインスタンスである）。
{s.getX} += s.printX;[ 2 ] Chiba, S., Igarashi, A., and Zakirov, S.: Mostly
modular compilation of crosscutting concerns bycontextual predicate dispatch, OOPSLA ’10, ACM,
2010, pp. 539–554.
[ 3 ] Elliott, C. and Hudak, P.: Functional reactiveanimation, ICFP ’97, ACM, 1997, pp. 263–273.
[ 4 ] Eugster, P. T. and Jayaram, K. R.: EventJava: An Extension of Java for Event Correlation.,
ECOOP ’09, 2009, pp. 570–594.
[ 5 ] Gamma, E., Helm, R., Johnson, R., and Vlissides, J.: Design Patterns, Addison-Wesley, 1994.
[ 6 ] Gasiunas, V., Satabin, L., Mezini, M., Núñez,A., and Noyé, J.: EScala: modular event-driven object interactions in Scala, AOSD ’11, ACM, 2011,
pp. 227–240.
[ 7 ] Kiczales, G., Lamping, J., Mendhekar, A.,Maeda, C., Lopes, C., marc Loingtier, J., and Irwin, J.: Aspect-oriented programming, ECOOP’97, Springer-Verlag, 1997.
[ 8 ] Maier, I. and Odersky, M.: Deprecating the Observer Pattern with Scala.React, Technical report,
2012.
[ 9 ] Meyerovich, L. A., Guha, A., Baskin, J., Cooper,
G. H., Greenberg, M., Bromfield, A., and Krish-namurthi, S.: Flapjax: a programming language
for Ajax applications, OOPSLA ’09, ACM, 2009,
pp. 1–20.
[10] Microsoft Corporation: C# language specification.
[11] Nilsson, H., Courtney, A., and Peterson, J.:
Functional reactive programming, continued, Proceedings of the 2002 ACM SIGPLAN workshop onHaskell, Haskell ’02, ACM, 2002, pp. 51–64.
[12] Rajan, H. and Leavens, G. T.: Ptolemy: A Language with Quantified, Typed Events., ECOOP ’08,2008, pp. 155–179.
[13] The Boost Project: Boost.Signals,
http://www.boost.org/libs/signals/.
[14] The Qt Project: Signals & Slots,
http://qt-project.org/doc/signalsandslots.
[15] Zhuang, Y. and Chiba, S.: Making Events Reactive with Implicit Bindings, (Submitted for publication).
[16] Zhuang, Y. and Chiba, S.: Method slots: supporting methods, events, and advices by a single
language construct, AOSD ’13, AOSD ’13, ACM,
2013, pp. 197–208.