ExampleChap3

「ExampleChap3」の編集履歴(バックアップ)一覧に戻る
ExampleChap3」を以下のとおり復元します。
* 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.

以下は Scala が特に向いたアプリケーション分野を示す例です。電子オークションサービスを実装する仕事を考えてみましょう。Erlang スタイルのアクタープロセスモデルをオークション参加者を実装する為に使用します。アクターはメッセージが送られるオブジェクトです。各アクターはやって来るメッセージの「メールボックス」を持ち、それはキューとして実現されます。メールボックスの中のメッセージを順番に処理する事も、あるパターンにマッチするメッセージを探す事も出来ます。

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. 

全ての取引される商品に対して競売人アクターがいて、取引される物の情報を公開し、クライアントからの申し込みを受け付け、取引を終わる為に売り手と落札者の通信を行います。ここでは簡単な実装を示します。

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. 

最初のステップとして、オークションの最中に交換されるメッセージを定義します。2つの抽象基底クラスがあり、AuctionMessage はクライアントからオークションサービスへのメッセージを、AuctionReply はサービスからクライアントへの返答です。両基底クラスには幾つものケースがあり、図 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: Message Classes for an Auction Service ---

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.

各基底クラスには、クラス内の特定のメッセージの形式を定める「ケースクラス」が幾つもあります。それらのメッセージは最終的には小さな XML 文書にうまくマップ出来るかもしれません。ここでは自動化ツールが存在して、上記の様に XML 文書と内部データ構造との間を変換するとしましょう。

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 

図 3.2 は 1つの品物に関する競りを調整するオークションアクターの為の、Auction クラスの Scala での実装です。このクラスのオブジェクトは下記を指示して作られます。

- 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. 

- オークションが終わった時に通知される必要のある売り手アクター
- 最低競売価格
- オークションが終わるべき時刻

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: 

- 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. 

 ---
 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: Implementation of an Auction Service ---

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 18.11. 

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.

----
#comment

復元してよろしいですか?

ツールボックス

下から選んでください:

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