弥生研究所

人は誰しもが生きることの専門家である

scala の implicit に対する防御策

paulownia.hatenablog.com

上記の記事は、示唆に富んだとてもよい記事で、同時に私と同じ疑問を持っていて、ひとつの道筋を提示してくれている。 どうやら、scala 界において、implicit に対する知識が私と同程度の人は多いとお見受けいたした。

ちなみに、私の言語知識は、C、JavaJavascript 程度で、ほかの言語は読み書きができる程度のものもあれば、まったく知らない言語もあり、広く深い知識というのはまったくない。そんな私が、仕事で Scala を書くようになって、implicit に対して考え始めたことがあったので、綴っておきたい。なお、私が言及しているのは、implicit parameter についてである。implicit conversion は推奨されていないの一言を見て以来、それ以上の知識を受け付けていない。

とにかく、現状のソースコードが、 implicit な引数をもつメソッドを呼び出すためだけに implicit な変数を用意しているという例が多すぎて、implicit の何が素晴らしいのか全く体感できていない。implicit な引数があるから、implicit な変数を定義しようというソースコードを書かれると、何を引数として渡しているのかソースコードから分かりにくくなるから、害悪でしかない。implicit の本来の意図は、多態性を提供するところにあるらしい。しかし、ここが正直なところ難しくて、この時点で脱落するプログラマは多数なのである。なので、implicit な引数を持つメソッドを書いたプログラマが、implicit の本来の意図を理解せず、引数を省略できる表面的な機能だけに着目している説は、かなり濃厚である。例えば、Actor の ask には timeout が implicit な引数として定義されているが、これはどういう多態性を想定しているわけか?

理解できない implicit との付き合い方

そこで、私は implicit の神髄を体得するまでの間、防御策として以下の対策を講じている。

  • 自分から implicit な引数を持つメソッドを書かないこと
  • imlicit な引数を持つメソッドを呼び出すとき、implicit な変数を用意しないで明示的に変数を渡すこと。

まず、implicit の仕様を理解しないで implict な引数を持つメソッドを書く破壊思想の持ち主はいないと思う。しかし、引数を省略できるという表面的な機能に着目して implicit つき引数をもつメソッドを定義する例は、残念ながら多いと邪推している。なので、メソッドを定義するとき、引数を implicit にするかどうかは慎重になるべきだ。迷っている場合は、あるいは思考停止したい場合は implicit は付けなくて良い。間違っても、引数を省略する意図で implicit をつけてはいけない。

次に、問題なのは、既に用意されている implicit な引数を持つメソッドをどう呼ぶかである。implicit について調べると、引数を省略して暗黙的に値を渡す機能であり、そして暗黙的に渡されるのは implicit が定義された変数であることが分かる。そうすると、implicit な引数を持つメソッドを呼び出すには、implicit な変数を用意するのは当然の流れとなり、思考停止して implicit な変数が定義されると、どこで使われているのか、何を渡しているのかが分かりづらくなるのは既に書いたとおりである。でも待ってほしい。implicit な引数を持つメソッドを呼び出すために、implicit な変数を定義する必要はないのである。引数に implicit が付いていても、明示的に変数を渡してもいいのである。なので、implicit つき引数をもつメソッドを呼び出すときは、まずは implicit な変数を定義するのではなく、明示的に変数を渡そう。

ところで、Scalaコンパイラが implicit な引数を見つけたときに何をするかというと、スコープの中から implicit な変数を探し出すらしい。そこで特定できないとコンパイルエラーとなる。は? 同じことをソースコードを読むプログラマがやれと? ソースコードを読んでいたら、どのメソッドが implicit 付きのメソッドかは定義を見ないと分からないし、直前に implicit な変数が定義されているならともかく、無遠慮にもフィールド変数として implicit な変数が定義されていようものなら、マジで血圧が上がるのである。このあたりの、ソースコードの読者に対する Scala の言語仕様の配慮のなさは、いったいどういう思想によるものなのだろう。

ソースコードは書かれるよりも読まれることが多い

そもそも、ソースコードの読み書きというのは、言語の仕様を理解して行うべきというのが正論なのだが、言語を自分で選ぶならともかく、選ぶ余地のない場合は、学習途上でも否応なく読み書きせざるをえない。そんなときに、後継の技術者たちにどれだけ優しいソースコードを残してやれるかというのが、私の技術者としての命題なのである。

Scala は難しいよ。Scala を理解できるほどの優秀な技術者だけが集まったプロジェクトであれば、そりゃあ技術的な負債とは縁のないプロジェクトになるかもしれない。言語として Scala を選択する理由は、そういう足切りの意味合いがあるのかもしれない。でも、すべてがそうはいかない。新人だっているだろうし、優秀に見える無能もいる。その点で、Java はどんな人が書いてもそれなりに冗長になるから、非常に防御的な言語だとつくづく思うのである。冗長さをデメリットだととらえる意見もあるが、私はそうは思わない。

結局、私の implicit に対する理解は進まないままである。引数を暗黙化するという表面的な機能だけの理解に止まり、メリットが何なのかを知らず、デメリットだけを体感している。implicit のメリットを知るにはもう少し時間が必要である。