ExampleChap3

「ExampleChap3」の編集履歴(バックアップ)一覧はこちら

ExampleChap3」(2012/09/19 (水) 12:41:19) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

#co(){ Chapter 3 Programming with Actors and Messages Here's an example that shows an application area for which Scala is particularly well suited. Consider the task of implementing an electronic auction service. We use an Erlang-style actor process model to implement the participants of the auction. Actors are objects to which messages are sent. Every actor has a "mailbox" of its incoming messages which is represented as a queue. It can work sequentially through the messages in its mailbox, or search for messages matching some pattern. } #setmenu2(ex-r-menu) * 第 3 章 アクターとメッセージによるプログラミング この章では、ある応用分野の例を見てゆきます。この分野は Scala がとてもよく似合っています。電子オークションサービスを実装する仕事を考えてみて下さい。Erlang 風のアクタープロセスモデルを使ってオークション参加者の実装をしましょう。アクターとはメッセージを受信するオブジェクトです。各アクターはメッセージ受信用の「メールボックス」を持ち、それはキューとして表現されます。メールボックス中のメッセージを順番に処理することも、特定のパターンにマッチするメッセージを検索することもできます。 #co(){ For every traded item there is an auctioneer actor that publishes information about the traded item, that accepts offers from clients and that communicates with the seller and winning bidder to close the transaction. We present an overview of a simple implementation here. } 取引される商品ごとに一つの競売人アクターがあり、そのアクターが、商品についての情報公開、クライアントからの申し込み受付け、取引終了時の売り手および落札者への通知します。ここでは簡単な実装の概要を示します。 #co(){ As a first step, we define the messages that are exchanged during an auction. There are two abstract base classes AuctionMessage for messages from clients to the auction service, and AuctionReply for replies from the service to the clients. For both base classes there exists a number of cases, which are defined in Figure 3.1. } 最初のステップとして、オークションでやり取りされるメッセージを定義します。クライアントからオークションサービスへのメッセージである AuctionMessage と、サービスからクライアントへの返答である AuctionReply の、2つの抽象基底クラス(abstrac base class)があります。両基底クラスには複数のケース(case)があり、図 3.1 で定義されています。 --- import scala.actors.Actor abstract class AuctionMessage case class Offer(bid: Int, client: Actor) extends AuctionMessage case class Inquire(client: Actor) extends AuctionMessage abstract class AuctionReply case class Status(asked: Int, expire: Date) extends AuctionReply case object BestOffer extends AuctionReply case class BeatenOffer(maxBid: Int) extends AuctionReply case class AuctionConcluded(seller: Actor, client: Actor) extends AuctionReply case object AuctionFailed extends AuctionReply case object AuctionOver extends AuctionReply --- Listing 3.1: オークションサービスのメッセージクラス --- #co(){ --- Listing 3.1: Message Classes for an Auction Service --- } #co(){ For each base class, there are a number of case classes which define the format of particular messages in the class. These messages might well be ultimately mapped to small XML documents. We expect automatic tools to exist that convert between XML documents and internal data structures like the ones defined above. } 各基底クラスごとに、クラス内の特定のメッセージ形式を定義する&bold(){ケースクラス}(case class)が複数あります。それらのメッセージが、小さな XML 文書に最終的にうまく対応できればよいのですが・・・。ここでは自動化ツールが存在すると仮定して、 XML 文書と、先のように定義された内部データ構造とを変換するとしましょう。 #co(){ Figure 3.2 presents a Scala implementation of a class Auction for auction actors that coordinate the bidding on one item. Objects of this class are created by indicating - a seller actor which needs to be notified when the auction is over, - a minimal bid, - the date when the auction is to be closed. } 図 3.2 で示す Scala 実装、Auction クラスは、ある商品のオークションを調整する競売人アクターのためのものです。このクラスのオブジェクトは、次を指定して生成されます。 - オークション終了時に通知する必要のある売り手アクター - 最低オークション価格 - オークションの終了予定時刻 #co(){ The behavior of the actor is defined by its act method. That method repeatedly selects (using receiveWithin) a message and reacts to it, until the auction is closed, which is signaled by a TIMEOUT message. Before finally stopping, it stays active for another period determined by the timeToShutdown constant and replies to further offers that the auction is closed. Here are some further explanations of the constructs used in this program: } アクターの振る舞いは act メソッドで定義されています。このメソッドでは 、TIMEOUT メッセージによってオークション終了が通知されるまで (receiveWithin を用いて) メッセージを選択し、それに対応することを繰り返します。最終的に停止する前まで、定数 timeToShutdown で定められた期間はアクティブであり続け、さらなる申し出に対してはオークションを締切った旨を返答します。 このプログラムで使われている構文について、さらにいくつか解説します。 #co(){ - The receiveWithin method of class Actor takes as parameters a time span given in milliseconds and a function that processes messages in the mailbox. The function is given by a sequence of cases that each specify a pattern and an action to perform for messages matching the pattern. The receiveWithin method selects the first message in the mailbox which matches one of these patterns and applies the corresponding action to it. - The last case of receiveWithin is guarded by a TIMEOUT pattern. If no other messages are received in the meantime, this pattern is triggered after the time span which is passed as argument to the enclosing receiveWithin method. TIMEOUT is a special message, which is triggered by the Actor implementation itself. - Reply messages are sent using syntax of the form destination ! SomeMessage. ! is used here as a binary operator with an actor and a message as arguments. This is equivalent in Scala to the method call destination.!(SomeMessage), i.e. the invocation of the ! method of the destination actor with the given message as parameter. } - クラス Actor の receiveWithin メソッドはパラメータとして、期間 (ミリ秒単位) とメールボックスのメッセージを処理する関数をとります。関数は一連のケースとして与えられ、各ケースはパターンと、そのパターンに対応したメッセージを処理するアクションを指定します。receiveWithin メソッドは、メールボックスからパターンにマッチする最初のメッセージを選び、対応するアクションを適用します。 - receiveWithin の最後のケースは TIMEOUT パターンで守られています。もし有効時間内にメッセージを受け取らなければ、receiveWithin メソッドの引数として渡された期間経過後に、このパターンが起動されます。TIMEOUT は特別なメッセージで、Actor の実装そのものによって起動されます。 - 応答メッセージを送信する構文として、destnation ! SomeMessage (宛先 ! メッセージ) を用います。ここで ! は、アクターとメッセージを引数とする二項演算子のように使われています。これは Scala では、メソッド呼び出し destination.!(SomeMessage)、すなわち、メッセージをパラメータとした destination アクターの ! メソッド呼び出しと同じです。 --- class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor { val timeToShutdown = 36000000 // msec val bidIncrement = 10 def act() { var maxBid = minBid - bidIncrement var maxBidder: Actor = null var running = true while (running) { receiveWithin ((closing.getTime() - new Date().getTime())) { case Offer(bid, client) => if (bid >= maxBid + bidIncrement) { if (maxBid >= minBid) maxBidder ! BeatenOffer(bid) maxBid = bid; maxBidder = client; client ! BestOffer } else { client ! BeatenOffer(maxBid) } case Inquire(client) => client ! Status(maxBid, closing) case TIMEOUT => if (maxBid >= minBid) { val reply = AuctionConcluded(seller, maxBidder) maxBidder ! reply; seller ! reply } else { seller ! AuctionFailed } receiveWithin(timeToShutdown) { case Offer(_, client) => client ! AuctionOver case TIMEOUT => running = false } } } } } --- Listing 3.2: オークションサービスの実装 --- #co(){ --- Listing 3.2: Implementation of an Auction Service --- } #co(){ The preceding discussion gave a flavor of distributed programming in Scala. It might seem that Scala has a rich set of language constructs that support actor processes, message sending and receiving, programming with timeouts, etc. In fact, the opposite is true. All the constructs discussed above are offered as methods in the library class Actor. That class is itself implemented in Scala, based on the underlying thread model of the host language (e.g. Java, or .NET). The implementation of all features of class Actor used here is given in Section 17.11. } ここまでの話は、Scala における分散プログラミングの雰囲気を示したものです。Scala にはアクタープロセス、メッセージ送受信、タイムアウトのあるプログラミングなどをサポートする豊富な言語構文があるように見えたかもしれません。実際は全く逆です。これまでに議論した言語構文はすべてクラス Actor のライブラリ内でメソッドとして提供されています。そのクラス自身が Scala で実装されており、基礎となるホスト言語 (つまり Java や .NET) のスレッドモデルに基づいています。ここで使った Actor クラスの特徴すべての実装については、17.11 節で述べられています。 #co(){ The advantages of the library-based approach are relative simplicity of the core language and flexibility for library designers. Because the core language need not specify details of high-level process communication, it can be kept simpler and more general. Because the particular model of messages in a mailbox is a library module, it can be freely modified if a different model is needed in some applications. The approach requires however that the core language is expressive enough to provide the necessary language abstractions in a convenient way. Scala has been designed with this in mind; one of its major design goals was that it should be flexible enough to act as a convenient host language for domain specific languages implemented by library modules. For instance, the actor communication constructs presented above can be regarded as one such domain specific language, which conceptually extends the Scala core. } ライブラリベースのアプローチの利点は、相対的な、コア言語の簡潔さとライブラリ設計者への柔軟性にあります。コア言語では高レベルなプロセス間通信の詳細を規定する必要がないので、簡潔、一般性を保つことができます。メールボックス内メッセージのこのモデルは単なるライブラリモジュールなので、あるアプリケーションが異なるモデルを必要とする場合は、自由に変更できます。しかしながら、このアプローチはコア言語に対して、必要とされる言語の抽象化を使いやすい形で提供できるような十分な表現力を要求します。Scala はこのことを念頭においてデザインされました。Scala デザインの大きな目標の一つは、ライブラリモジュールによって実装される、ドメイン特化言語(DSL)ための使いやすいホスト言語たりうる、柔軟性にあります。たとえば先に示したアクター間通信の構文は、そのようなドメイン特化言語とみることができ、無意識に Scala コアを拡張しています。 #center(){[[前ページ>ExampleChap2]] [[ 3 章>ExampleChap3]] [[目次>ScalaByExample和訳]] [[次ページ>ExampleChap4]]} ---- 「actor process model」が不明です。Erlang-styleならば「Actor model」では? 「case object」の説明は無し? ーーーーー修正案 by ryugate ※ 修正案を取り入れました。 TIMEOUT は特別なメッセージで、Actor の実装そのものにトリガーされます。 →TIMEOUT は特別なメッセージで、Actor の実装そのものによってトリガーされます。 - ご指摘どうもありがとうございます>ryugateさん。 -- tmiya (2008-05-14 06:59:29) - 抽象基底クラス(abstrac base class)} -- kariya_mitsuru (2012-09-19 00:54:58) - すみません、途中で送信してしまいました。「抽象基底クラス(abstrac base class)」⇒「抽象基底クラス(abstract base class)」です。 -- kariya_mitsuru (2012-09-19 00:57:07) - { -- kariya_mitsuru (2012-09-19 00:57:55) - 何度もすみません・・・「might well」は「~良いのですが」ではなく「~でしょう」ではないでしょうか? -- kariya_mitsuru (2012-09-19 01:00:17) #comment
#co(){ Chapter 3 Programming with Actors and Messages Here's an example that shows an application area for which Scala is particularly well suited. Consider the task of implementing an electronic auction service. We use an Erlang-style actor process model to implement the participants of the auction. Actors are objects to which messages are sent. Every actor has a "mailbox" of its incoming messages which is represented as a queue. It can work sequentially through the messages in its mailbox, or search for messages matching some pattern. } #setmenu2(ex-r-menu) * 第 3 章 アクターとメッセージによるプログラミング この章では、ある応用分野の例を見てゆきます。この分野は Scala がとてもよく似合っています。電子オークションサービスを実装する仕事を考えてみて下さい。Erlang 風のアクタープロセスモデルを使ってオークション参加者の実装をしましょう。アクターとはメッセージを受信するオブジェクトです。各アクターはメッセージ受信用の「メールボックス」を持ち、それはキューとして表現されます。メールボックス中のメッセージを順番に処理することも、特定のパターンにマッチするメッセージを検索することもできます。 #co(){ For every traded item there is an auctioneer actor that publishes information about the traded item, that accepts offers from clients and that communicates with the seller and winning bidder to close the transaction. We present an overview of a simple implementation here. } 取引される商品ごとに一つの競売人アクターがあり、そのアクターが、商品についての情報公開、クライアントからの申し込み受付け、取引終了時の売り手および落札者への通知します。ここでは簡単な実装の概要を示します。 #co(){ As a first step, we define the messages that are exchanged during an auction. There are two abstract base classes AuctionMessage for messages from clients to the auction service, and AuctionReply for replies from the service to the clients. For both base classes there exists a number of cases, which are defined in Figure 3.1. } 最初のステップとして、オークションでやり取りされるメッセージを定義します。クライアントからオークションサービスへのメッセージである AuctionMessage と、サービスからクライアントへの返答である AuctionReply の、2つの抽象基底クラス(abstract base class)があります。両基底クラスには複数のケース(case)があり、図 3.1 で定義されています。 --- import scala.actors.Actor abstract class AuctionMessage case class Offer(bid: Int, client: Actor) extends AuctionMessage case class Inquire(client: Actor) extends AuctionMessage abstract class AuctionReply case class Status(asked: Int, expire: Date) extends AuctionReply case object BestOffer extends AuctionReply case class BeatenOffer(maxBid: Int) extends AuctionReply case class AuctionConcluded(seller: Actor, client: Actor) extends AuctionReply case object AuctionFailed extends AuctionReply case object AuctionOver extends AuctionReply --- Listing 3.1: オークションサービスのメッセージクラス --- #co(){ --- Listing 3.1: Message Classes for an Auction Service --- } #co(){ For each base class, there are a number of case classes which define the format of particular messages in the class. These messages might well be ultimately mapped to small XML documents. We expect automatic tools to exist that convert between XML documents and internal data structures like the ones defined above. } 各基底クラスごとに、クラス内の特定のメッセージ形式を定義する&bold(){ケースクラス}(case class)が複数あります。それらのメッセージが、小さな XML 文書に最終的にうまく対応できればよいのですが・・・。ここでは自動化ツールが存在すると仮定して、 XML 文書と、先のように定義された内部データ構造とを変換するとしましょう。 #co(){ Figure 3.2 presents a Scala implementation of a class Auction for auction actors that coordinate the bidding on one item. Objects of this class are created by indicating - a seller actor which needs to be notified when the auction is over, - a minimal bid, - the date when the auction is to be closed. } 図 3.2 で示す Scala 実装、Auction クラスは、ある商品のオークションを調整する競売人アクターのためのものです。このクラスのオブジェクトは、次を指定して生成されます。 - オークション終了時に通知する必要のある売り手アクター - 最低オークション価格 - オークションの終了予定時刻 #co(){ The behavior of the actor is defined by its act method. That method repeatedly selects (using receiveWithin) a message and reacts to it, until the auction is closed, which is signaled by a TIMEOUT message. Before finally stopping, it stays active for another period determined by the timeToShutdown constant and replies to further offers that the auction is closed. Here are some further explanations of the constructs used in this program: } アクターの振る舞いは act メソッドで定義されています。このメソッドでは 、TIMEOUT メッセージによってオークション終了が通知されるまで (receiveWithin を用いて) メッセージを選択し、それに対応することを繰り返します。最終的に停止する前まで、定数 timeToShutdown で定められた期間はアクティブであり続け、さらなる申し出に対してはオークションを締切った旨を返答します。 このプログラムで使われている構文について、さらにいくつか解説します。 #co(){ - The receiveWithin method of class Actor takes as parameters a time span given in milliseconds and a function that processes messages in the mailbox. The function is given by a sequence of cases that each specify a pattern and an action to perform for messages matching the pattern. The receiveWithin method selects the first message in the mailbox which matches one of these patterns and applies the corresponding action to it. - The last case of receiveWithin is guarded by a TIMEOUT pattern. If no other messages are received in the meantime, this pattern is triggered after the time span which is passed as argument to the enclosing receiveWithin method. TIMEOUT is a special message, which is triggered by the Actor implementation itself. - Reply messages are sent using syntax of the form destination ! SomeMessage. ! is used here as a binary operator with an actor and a message as arguments. This is equivalent in Scala to the method call destination.!(SomeMessage), i.e. the invocation of the ! method of the destination actor with the given message as parameter. } - クラス Actor の receiveWithin メソッドはパラメータとして、期間 (ミリ秒単位) とメールボックスのメッセージを処理する関数をとります。関数は一連のケースとして与えられ、各ケースはパターンと、そのパターンに対応したメッセージを処理するアクションを指定します。receiveWithin メソッドは、メールボックスからパターンにマッチする最初のメッセージを選び、対応するアクションを適用します。 - receiveWithin の最後のケースは TIMEOUT パターンで守られています。もし有効時間内にメッセージを受け取らなければ、receiveWithin メソッドの引数として渡された期間経過後に、このパターンが起動されます。TIMEOUT は特別なメッセージで、Actor の実装そのものによって起動されます。 - 応答メッセージを送信する構文として、destnation ! SomeMessage (宛先 ! メッセージ) を用います。ここで ! は、アクターとメッセージを引数とする二項演算子のように使われています。これは Scala では、メソッド呼び出し destination.!(SomeMessage)、すなわち、メッセージをパラメータとした destination アクターの ! メソッド呼び出しと同じです。 --- class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor { val timeToShutdown = 36000000 // msec val bidIncrement = 10 def act() { var maxBid = minBid - bidIncrement var maxBidder: Actor = null var running = true while (running) { receiveWithin ((closing.getTime() - new Date().getTime())) { case Offer(bid, client) => if (bid >= maxBid + bidIncrement) { if (maxBid >= minBid) maxBidder ! BeatenOffer(bid) maxBid = bid; maxBidder = client; client ! BestOffer } else { client ! BeatenOffer(maxBid) } case Inquire(client) => client ! Status(maxBid, closing) case TIMEOUT => if (maxBid >= minBid) { val reply = AuctionConcluded(seller, maxBidder) maxBidder ! reply; seller ! reply } else { seller ! AuctionFailed } receiveWithin(timeToShutdown) { case Offer(_, client) => client ! AuctionOver case TIMEOUT => running = false } } } } } --- Listing 3.2: オークションサービスの実装 --- #co(){ --- Listing 3.2: Implementation of an Auction Service --- } #co(){ The preceding discussion gave a flavor of distributed programming in Scala. It might seem that Scala has a rich set of language constructs that support actor processes, message sending and receiving, programming with timeouts, etc. In fact, the opposite is true. All the constructs discussed above are offered as methods in the library class Actor. That class is itself implemented in Scala, based on the underlying thread model of the host language (e.g. Java, or .NET). The implementation of all features of class Actor used here is given in Section 17.11. } ここまでの話は、Scala における分散プログラミングの雰囲気を示したものです。Scala にはアクタープロセス、メッセージ送受信、タイムアウトのあるプログラミングなどをサポートする豊富な言語構文があるように見えたかもしれません。実際は全く逆です。これまでに議論した言語構文はすべてクラス Actor のライブラリ内でメソッドとして提供されています。そのクラス自身が Scala で実装されており、基礎となるホスト言語 (つまり Java や .NET) のスレッドモデルに基づいています。ここで使った Actor クラスの特徴すべての実装については、17.11 節で述べられています。 #co(){ The advantages of the library-based approach are relative simplicity of the core language and flexibility for library designers. Because the core language need not specify details of high-level process communication, it can be kept simpler and more general. Because the particular model of messages in a mailbox is a library module, it can be freely modified if a different model is needed in some applications. The approach requires however that the core language is expressive enough to provide the necessary language abstractions in a convenient way. Scala has been designed with this in mind; one of its major design goals was that it should be flexible enough to act as a convenient host language for domain specific languages implemented by library modules. For instance, the actor communication constructs presented above can be regarded as one such domain specific language, which conceptually extends the Scala core. } ライブラリベースのアプローチの利点は、相対的な、コア言語の簡潔さとライブラリ設計者への柔軟性にあります。コア言語では高レベルなプロセス間通信の詳細を規定する必要がないので、簡潔、一般性を保つことができます。メールボックス内メッセージのこのモデルは単なるライブラリモジュールなので、あるアプリケーションが異なるモデルを必要とする場合は、自由に変更できます。しかしながら、このアプローチはコア言語に対して、必要とされる言語の抽象化を使いやすい形で提供できるような十分な表現力を要求します。Scala はこのことを念頭においてデザインされました。Scala デザインの大きな目標の一つは、ライブラリモジュールによって実装される、ドメイン特化言語(DSL)ための使いやすいホスト言語たりうる、柔軟性にあります。たとえば先に示したアクター間通信の構文は、そのようなドメイン特化言語とみることができ、無意識に Scala コアを拡張しています。 #center(){[[前ページ>ExampleChap2]] [[ 3 章>ExampleChap3]] [[目次>ScalaByExample和訳]] [[次ページ>ExampleChap4]]} ---- 「actor process model」が不明です。Erlang-styleならば「Actor model」では? 「case object」の説明は無し? ーーーーー修正案 by ryugate ※ 修正案を取り入れました。 TIMEOUT は特別なメッセージで、Actor の実装そのものにトリガーされます。 →TIMEOUT は特別なメッセージで、Actor の実装そのものによってトリガーされます。 - ご指摘どうもありがとうございます>ryugateさん。 -- tmiya (2008-05-14 06:59:29) - 「might well」は「~良いのですが」ではなく「~でしょう」ではないでしょうか? -- kariya_mitsuru (2012-09-19 01:00:17) #comment

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。