リフレクションを使わずに new T を再現する手段 on Scala

## new T って何さ

こんなやつのことを言ってます

```scala
trait Foo {
  def foo: String
}
def execute[T <: Foo] = {
  val instance = new T // これ
  println(instance.foo)
}
```

型パラメータで指定された型のインスタンスを直接つくりたいというのは、フレームワークやライブラリの開発中に誰しも一度くらい経験があるとおもいます。が、これはもちろん無理です。Java や Scala では型パラメータが type erasure によって消されてしまうためです。

Java であっても Scala であってもリフレクションを駆使することで解決できる場面はなくもないですが、後述するように様々な問題を孕んでいるため、この記事では別なアプローチについて考えます

## new T の可否について

本題に入る前に少しおさらいしておきましょう

* そもそも new T は必要なのか
  * 具象型のファクトリを渡せばいい話だろう
     * しかしそれを毎回実装しなければいけないというのも…
* new T は安全に使えるのだろうか
  * デフォルトコンストラクタがない場合はどうなる
     * 不完全なオブジェクトを作って再代入しまくるか
     * それとも実行時にクラッシュか
* リフレクションの問題もいくつかあるよね
  * スレッドセーフじゃないし実行速度も不安
     * つまり避けられるなら避けたい

この辺りの議論についてはググるとたくさん出てきますが、まとめるとこんな感じです

* new T の需要はある
* とはいえ危険性があるのも確か

## つまり : 型パラメータからインスタンスを生成する安全な方法がほしい！

この問題はシンプルな trait によって解決できます。
そう、Scala ならね

```scala
trait HasConstructor[A]{
  def newInstance: A
}
object HasConstructor {
  type HasDefaultConstructor[A] = HasConstructor[() => A]
}
def execute[A <: Foo: HasDefaultConstructor]() = {
  val instance = implicitly[HasDefaultConstructor[A]].newInstance()
  println(instance.foo)
}
```

`HasConstructor` という trait を導入しました。これは文字通り「型 A にはコンストラクタがある」ことをコンパイラに示すための型です。`execute` メソッドにはその他に一切余計な制限が足されていない点に注目してください。`HasConstructor[() => A]` の implicit 定義さえ用意されていればどんな `Foo` 型も渡せます。

この `execute` の呼び出し側のコードは :

```scala
class CustomFoo extends Foo {
  override def foo = "hello!"
}
object CustomFoo {
  implicit object constructor extends HasConstructor[() => CustomFoo]{
    def newInstance = () => new CustomFoo
  }
}
execute[CustomFoo]()// hello!
execute[Foo]()// compile error
```

残念ながらあまり綺麗ではありませんね…。
とはいえこの時点で目的の要件は全て守れています

* `CustomFoo` という型パラメータを指定するだけで呼び出せている
  * `execute` の利用者は明示的に new しなくていい
* new できない型が渡されてもコンパイル時に検出できている
* リフレクションも全く使っていない

ここでは implicit 定義によってインスタンスの生成方法を記述していますが、`CustomFoo` のコンストラクタに引数がないことは見ればわかります。どうにかしてそれをコンパイラに知らせることはできないものでしょうか

## つまり : implicit の実装を毎回手作業で書きたくない！

この問題は数十行のマクロによって解決できます。
そう、Scala ならね（しつこい）

```scala
object HasConstructor {
  implicit def reify[A]: HasConstructor[A] = macro ReificationImpl.infer[A]
  type HasDefaultConstructor[A] = HasConstructor[() => A]
}
private object ReificationImpl {
  def infer[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
    val factory = new ReificationFactory { override val context: c.type = c }
    val tree = factory createConstructor c.weakTypeOf[A]
    // println(tree)
    tree
  }
}
trait ReificationFactory {
  val context: blackbox.Context
  import context.universe._

  def createConstructor(target: Type): Tree = {
    if (!target.typeSymbol.fullName.startsWith("scala.Function")){
      val name = typeOf[HasConstructor[_]].typeSymbol.name.encodedName
      val message = s"FunctionN must be applied to $name. current: $target"
      throw new IllegalArgumentException(message)
    }
    val newInstance = target.typeArgs match {
      case xs :+ last =>
        val args = xs map { x =>
          val arg = TermName(context freshName "x")
          q"$arg: $x"
        }
        q"(..$args) => new $last(..$args)"
      case x =>
        throw new IllegalArgumentException(s"unknown type: $x")
    }
    val constructor = appliedType(
      typeOf[HasConstructor[_]].typeConstructor,
      target
    )
    q"""new $constructor {
      override def newInstance = $newInstance
    }"""
  }
}
```

`object HasConstructor` にマクロを呼び出すための `implicit def` を追加しました。これによって呼び出し側のコードから退屈な implicit 実装を消すことができます

```scala
class CustomFoo extends Foo {
  override def foo = "hello!"
}
execute[CustomFoo]()// hello!
execute[Foo]()// compile error
```

明示的に new を書くだけの簡単なお仕事はもう必要ありません。もちろん前項で挙げていた要件も全て守られています。

一件落着！…ではありますが、せっかくなのでもう少し一般化してみます

## 引数が必要なコンストラクタにも対応したい！

聡明な読者の方々はお気づきかもしれません。ここまでの `type HasDefaultConstructor` はあくまで `HasConstructor[() => A]` のエイリアスであり、これは「引数 0 個で A を生成できる」という意味でした。今度は「引数 1 個から A を生成できる」パターンについても試してみましょう

```scala
class CustomFoo2(arg: String) extends Foo {
  override def foo = s"Hello, $arg!"
}
def execute2[A <: Foo](arg: String)(implicit i: HasConstructor[String => A]) = {
  val instance = i.newInstance(arg)
  println(instance.foo)
}
execute2[CustomFoo2]("World")// Hello, World!
execute2[CustomFoo]("boooo")// compile error
```

実は `HasConstructor` はこのままで問題なく動いてくれます。

`execute2` の定義に足されている `[String => A]` によって「コンストラクタが String 一つを受け取れるような Foo なら何でもいいよ」という情報がマクロに伝わっているためです。`CustomFoo` には String を受け取るようなコンストラクタは存在しないので無事にコンパイル時にエラーになります。

ちなみに `execute` のときと同じ記法で `execute2` の implicit 引数を消すこともできますが…

```scala
def execute2[A <: Foo: ({ type L[X] = HasConstructor[String => X] })#L](arg: String) = {
  val instance = implicitly[HasConstructor[String => A]].newInstance(arg)
  println(instance.foo)
}
```

お世辞にも読みやすくはありません。このあたりは現在の Scala の限界ですね

## まとめ

new T の抱える問題は implicit によって解決できる

 * 型安全にインスタンスを生成できる
 * リフレクションを使わないのでスレッドセーフ、速度も心配なし
 * リフレクションに頼れない Android のような環境でも問題なし

## ヒント

用語について

* 上記 `HasConstructor` は型クラス
  * 今回のマクロではこの型クラスのインスタンスを生成している
* `({ type L[X] = ... })#L` は type lambda と呼ばれている記法
  * 型引数が一つの型をその場で取り出すために使われる

参考リンク

* [Implicit Macros](http://docs.scala-lang.org/overviews/macros/implicits)
* [Quasiquotes](http://docs.scala-lang.org/overviews/quasiquotes/intro.html)