implicit parameters の使い方

implicit conversions に続いて、implicit parameters も使ってみました。

以下、implicit parameters を使用している関数の例。

abstract class Foo
def foo(msg: String)(implicit p: Foo) = println(msg + p)

implicit parameters の引数リストは一番最後に定義する必要があります。つまり、foo(implicit p: Foo)(msg: String) ではダメってことです。
あと、複数の引数を implicit parameters として定義できます。foo(msg: String)(implicit p1: Foo, p2: Hoge, ...) とかはありってことです。

実際に関数を呼び出す時は、implicit parameters の候補とする値に対して、implicit を付加しておきます。

implicit val bar = new Foo { override def toString = "Bar" }
foo("Hello")

object も候補にできます。

implicit object Bar extends Foo { override def toString = "Bar" }
foo("Hello")

ScalaByExample.pdf の例では、Generics とうまく組み合わせて適切なオブジェクトが implicit parameters に渡されるようにしています。これならば、型に依存する部分とそうでない部分を分離した上で、型に依存する部分の部品の選択をコンパイラにやらせることが出来そうですね。

アクターモデルでの、アクターの粒度に悩む

※自分用メモ
アクターモデルを利用した場合に、それぞれのアクターはどのような粒度とするのが良いのか?

なんとなく理解したこと

  • 単にスレッドの代替として使用するのであれば並列化したいところにだけ使えば良い
    • 実装方法の一つでしかない
    • 並列化そのものが目的
  • 問題領域を表すモデルとして考えた場合、すべての登場人物をアクターとして定義する?
    • モデリング方法の一つ
    • アクターモデル自体が、最初から並列化を前提としている
    • アクターモデルとしてモデル化/実装した場合、結果として並列化されている
    • 問題点/考慮点
      • アクターごとに閉じた状態を持つと考えられる
        • アクターの粒度が細かすぎると、データの一貫性を保てない/保ちづらい
        • 複数のアクターにまたがるようなトランザクションは考えづらい
      • 非同期メッセージによる協調動作を前提と考える
        • 相手が受信できる/していることを保証しない
          • scala.actors.remote が例外握りつぶしなのも、この考え方によるものかも?
      • 送信順にメッセージを受信するとは限らない
        • Scala の場合はどうなのか?
        • 必要であればメッセージの並び替えをするアクターを用意する

参考

アクターそれぞれが状態を持つことになるでしょうが、ある「状態」を複数のスレッドで処理する場合、つまり、複数のアクターがあるアクターが持つ単一の「状態」を元になんらかの処理を行う場合、元になる状態が可変であるとシステム全体で情報の不整合が発生しうるということです。

アクターモデルの基本は「全てのものはアクターである」という哲学である。これはオブジェクト指向プログラミングにおける「全てのものはオブジェクトである」という考え方と似ているが、オブジェクト指向ソフトウェアでは基本的に逐次的に実行するのに対して、アクターモデルでは本質的に並行性を備えている点が異なる。

アクターモデル使用時に、気に留めておいた方がよさげなこと

  • アクター間で制約は無い
  • メッセージは投げっぱなし
  • 処理有無、処理結果を期待しない
  • アクター内で、トランザクション、状態、処理について閉じている
  • インタフェースはメッセージパッシングのみ


とりあえず、サブシステムとして分離できる粒度をアクターとすることにした。