Help us understand the problem. What is going on with this article?

詳説implicitly(あるいはimplicitlyは黒魔術でないことの説明)

Scalaを日頃使っている方なら、一度は、

val instance = implicitly[Hoge[T]]
instance.hoge()

あるいは

implicitly[Hoge[T]].hoge()

のようなコードを書いたことがあるのではないかと思います。この implicitly というメソッドですが、しばしばScalaの黒魔術であると思われるようです(誰か特定の方の発言ではなくて、そういう趣旨の発言を時々みかけます)。

しかし、この implicitly 、定義を見てみるとわかるのですが、実は以下のたった一行のメソッドです。

@inline def implicitly[T](implicit e: T): T = e

@inline は最適化のためのヒントで特に意味はないですが、要は単一のimplicit parameterを取ってそれをそのまま返しているだけです。これに対して、たとえば implicitly[Hoge[T]] という呼び出しをすると、implicitなHoge[T]型の値を要求して、それをそのまま返すことになるわけです。

実のところ、implicit parameterを明示的に宣言している場合は、implicitly は必要ありません(上の定義を見ればわかるように、宣言した引数名でアクセスすればいいわけですから)。

問題は、implicit parameterを取るメソッドを定義するためのシンタックスシュガーであるcontext boundsを使ったときです。たとえば、

def sum[A](xs: List[A])(implicit num: Numeric[A]): A = ???

という定義は、

def sum[A:Numeric](xs: List[A]): A = ???

と書くことができます(A:Numericのような書き方をcontext boundsと呼びます)。

このとき、内部的には implicit evidence$1: Numeric[A] のような形でimplicit parameterが宣言されるのですが、evidence$1という引数にアクセスする方法がありません。実装にべったりで良ければ evidence$1 という内部的に生成される識別子そのものでアクセスできますが(Scala 2.13.0で確認)、それが危ない(内部実装が変わってもアクセスできることが保証されない)ことは言うまでもありません。

しばしば implicitly が黒魔術として思われるのは、おそらく、 implicit parameterという概念(もしくは、その元ネタである型クラス)が耳慣れないことに起因するのだと思います。また、implicitly というメソッド名も、その「黒魔術っぽい」印象を増した要因ではないかとも思います。

こういう「なんとなく黒魔術っぽい」系の話は、Scalaの他の箇所でもしばしば聞かれることがあるのですが、実は蓋を開けてみれば凄く単純であることが少なくありません。一方で、マクロや型システムを駆使した 本当の黒魔術 (たとえばshapelessが実現しているような)があるのがややこしいところですが、そういうのはほとんどが、言語仕様に定義されているものでもなければ、標準ライブラリで定義されているものでもなく、単なるサードパーティのライブラリ(言語の基本機能ではなく、機能を応用してできたもの)なので、その辺の違いを区別することが重要だというのが、ひとつ言えることかなと思います。

余談ですが、この implicitly あるいは、 implicit parameter というのがわかりにくいという理由もあり、Scala 3ではよりわかりやすく、かつ、使いやすい形に改良されています。詳しくは、この辺 とかこの辺 を参照してみてください(Scala 3の言語機能は、キーワードや細かい構文についてはまだ変更される可能性がある点に注意)。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away