Java.use(better); Episode#21 ファインダーを作成する

前の記事記事一覧|次の記事》
Java.use(better, Scala);


Episode#21

ファインダーを作成する:開け胡麻



新しいアイデアというのは
新しい場所におかれた古いアイデアなんだ
http://en.wikipedia.org/wiki/Dale_Dauten

《関連記事》

□ match 式とポリモフィズム


match 式をメソッド呼び出しと見なすなら、その対象に任意のオブジェクトを指定できるので「ポリモフィズム」を体現しているのが分ります。

同じメソッド呼び出しでも、オブジェクトごとに異なる振舞を示します。というのも、そのメソッドをどのように解釈するかを、オブジェクト自身が判断する仕掛を用意できるからです。次のコードの断片

scala> x.run

を見て、どのような様子を想像しますか。

scala> x = new Person; x.run
two legs

x が人なら、二本足で疾走する様を想像できるでしょう。

scala> x = new Dog; x.run
four legs

x が犬なら、四本足で疾走する様を想像できるでしょう。

scala> x = new Car; x.run
wheel tracks

x が車なら、そこに残るタイヤの跡を想像できるでしょう。

scala> x = new Computer; x.run
move about

x がコンピューターなら、それが部屋中を動き回るとは想像しないでしょう。世間ではこれを「バグ」と呼びます。

オブジェクト指向の醍醐味は「オブジェクトにメッセージを送る」という原則に沿って、すべての現象を説明できることです。さらに、ポリモフィズムを活用すると、同じメッセージに呼応して、その状況で最適な問題解決が図れます。

scala> val s = List(new Person, new Dog, new Car)
...
scala> s foreach { _.run }
two legs
four legs
wheel tracks

この事例では、同じメッセージ run に呼応して、オブジェクトごとに異なる挙動を示します。それが可能になるのは、そのメッセージの解釈を、コンパイラーに委ねるのではなく「オブジェクト自身が判断する」仕掛を用意できるからです。そのことを端的に示したのが、次のコードの断片です。

trait X { def run }
class Person extends X { def run = println("two legs") }

あるコミュニティーの中で通用する規則 trait X を逸脱しない範囲でなら、オブジェクトは自由に活動できます。そこで、前述したコードの断片を書き換えると、

scala> s foreach { case x => x.run }
...

ポリモフィズムを期待している状況でも、条件選択は可能です。この case は冗長ですが、そこにコンパイラーが干渉する余地が残ります。

scala> s foreach {
     |   case x: Person => x.run
     |   case x: Dog    => x.run
     |   case x: Car    => x.run
     | }
...

ここでは、ポリモフィズムを期待している状況と知りながら、それを無視するかのように、コンパイラーが干渉します。型付きパターンによって条件選択を迫る必要はありません。というのも、同じメッセージ run に呼応して、オブジェクトごとに異なる挙動を示せるからです。

scala> s foreach { any =>
     |   any match {
     |     case x: Person => println("two legs")
     |     case x: Dog    => println("four legs")
     |     case x: Car    => println("wheel tracks")
     |   }
     | }
...

これを見ると、ポリモフィズムを実現するために、クラスごとに分散させていたコードの断片が、一堂に会して、インライン展開されているかのようです。つまり、case ... => ... という形式は、名前を持たないメソッド呼び出しを、関数リテラルで表現したにすぎないのが分ります。

┃未来への考察

match 式は、ポリモフィズムに貢献するオブジェクト群が集う場を提供するだけで、その問題解決をオブジェクト自身に委ねることに変わりはありません。パターンマッチングに貢献するコンストラクターパターンは、Scala の特徴でもある拡張性〔= scalability〕を端的に示す好例のひとつです。それを象徴するのが、メソッド unapply の存在です。

ポリモフィズムの恩恵には、算譜(プログラム)もさることながら、作譜(プログラミング)によって浴することができます。たとえば、新たな対象として

scala> x = new Stream; x.run

が必要になると、match 式とポリモフィズムとのトレードオフ問題に直面します。このとき、いくつの視座を持ち寄れるかで、プログラマーの力量が問われます。


》作業中です《

 ↑ TOP

Created: 2010/05/23|Last updated: 2013/06/03 22:50:00