問題
scalaで型パラメータをまるで引数のようにしてパターンマッチしたい。
def func[T](): String = {
// 理想的にはこう書けると嬉しい
T match {
case Int => "いんと!"
case Long => "ろんぐ!"
case _ => "そのた!"
}
}
println(func[Int]) // いんと!
println(func[Long]) // ろんぐ!
println(func[Float]) // そのた!
2018/10/28 追記
コメント欄で指摘して頂いた通り、型パラメータに対してpattern matchを行いたいという要望自体に問題がある可能性が高いです。
リンク先で書かれている通り、型クラス・ポリモーフィズムやoverloadingで解決したほうが良いケースは多いでしょう。
解決策
リフレクションのClassTagを利用する。
ただ、僕が調べた限りだとScalaの言語上の制約によりpattern match構文を使っても簡潔には書けない。
1. if-elseチェーンを使う
import scala.reflect._
def func[T:ClassTag](): String = {
if (implicitly[ClassTag[T]] == classTag[Int])
"いんと!"
else if (implicitly[ClassTag[T]] == classTag[Long])
"ろんぐ!"
else
"そのた!"
}
2. pattern match with if guardを使う
import scala.reflect._
def func[T: ClassTag](): String = {
implicitly[ClassTag[T]] match {
case x if x == classTag[Int] => "いんと!"
case x if x == classTag[Long] => "ろんぐ!"
case _ => "そのた!"
}
}
3. 先頭が大文字の変数へ一度代入を行ったのちpattern matchを行う
import scala.reflect._
def func[T: ClassTag](): String = {
val IntClassTag = classTag[Int]
val LongClassTag = classTag[Long]
implicitly[ClassTag[T]] match {
case IntClassTag => "いんと!"
case LongClassTag => "ろんぐ!"
case _ => "そのた!"
}
}
蛇足
これら以外のパターンやもっと簡潔に書く方法があればぜひ教えてください。