LoginSignup
3

More than 5 years have passed since last update.

Scalaのリフレクションでメソッド一覧をテキスト出力

Last updated at Posted at 2014-10-08

目的

Scala 2.10から、メタプログラミングの一種であるリフレクション機能が入っています。
Reflection - 概要 - Scala Documentation

import scala.reflect.runtime.universe._

宇宙をインポートとか熱いですね……!

遊んでみたかったので、型を与えると簡易ScalaDocを出力するようなもの、つまり、

printMethods[List[Int]]

とすると、Scala Standard Library 2.11.2 - List のメソッド抜粋のような感じで、

...
addString(b: StringBuilder): StringBuilder
addString(b: StringBuilder, sep: String): StringBuilder
addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder
aggregate[B](z: => B)(seqop: (B, A) => B, combop: (B, B) => B): B
andThen[C](k: B => C): PartialFunction[A,C]
apply(n: Int): A
applyOrElse[A1][B1](x: A1, default: A1 => B1): B1
asInstanceOf[T0]: T0
...

を出力するものを、Scala2.11で書いてみました。
ただし、型パラメータのlower/upper boundの取得方法が分からずじまい……。

コード

リフレクションはまだEXPERIMENTALな機能なので、Scala 2.12以上では動かなくなるかも。
2.10で書いたコードを2.11に上げたら、deprecatedになっているものが幾つかありました。

HelloUniverse.scala
object HelloUniverse extends App {

  implicit class RichList[T](self: List[T]) {
    def mkStringIfNonEmpty[T](start: String,
                              seq: String,
                              end: String): String =
      if (self.nonEmpty) self.mkString(start, seq, end)
      else ""
  }

  import scala.reflect.runtime.universe._

  def paramToString(param: Symbol): String =
    (if (param.isImplicit) "implicit " else "") +
      param.name +
      ": " +
      param.typeSignature

  def methodToString(method: MethodSymbol): String =
    method.name.decodedName +
      method.typeParams.map(
        _.name
      ).mkStringIfNonEmpty("[", "][", "]") +
      method.paramLists.map(
        _.map(paramToString).mkString(", ")
      ).mkStringIfNonEmpty("(", ")(", ")") +
      ": " +
      method.returnType

  def printMethods[T: TypeTag] =
    typeOf[T].
      members.
      filter(_.isMethod).
      map(_.asMethod).
      map(methodToString).
      toArray.
      sorted.
      foreach(println)

  printMethods[List[Int]]
}
build.properties
sbt.version=0.13.6
build.sbt
name := "hello_universe"

version := "1.0"

scalaVersion := "2.11.2"

libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value

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
3