LoginSignup
1
0

More than 5 years have passed since last update.

Scalaで型パラメータそのものに対してpattern matchを行う方法

Last updated at Posted at 2018-09-21

問題

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 _ => "そのた!"
  }
}

蛇足

これら以外のパターンやもっと簡潔に書く方法があればぜひ教えてください。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0