LoginSignup
1
0

More than 5 years have passed since last update.

健忘録: Scala 2.11でDef Macroを使う時の手順と動くサンプルコード

Posted at

ただの健忘録。

build.sbt に以下を追加。

scalacOptions in Global += "-language:experimental.macros"

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

以下みたいな感じで書く。準クオートで書くprintlnマクロはこんな感じ。

import language.experimental.macros
import scala.reflect.macros.whitebox.Context

object PrintMacro {
  def p(msg: String): Unit = macro impl

  def impl(c: Context)(msg: c.Expr[String]) = {
    import c.universe._
    q"""
        println(${msg})
      """
  }
}

とか、変数名デバッグマクロとか作るときは、構文木作れるreify/spliceが便利。

import language.experimental.macros
import scala.reflect.macros.whitebox.Context

object DebugMacro {
  def debug(param: Any): Unit = macro debug_impl

  def debug_impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
    import c.universe._
    val paramRep = show(param.tree)
    val paramRepTree = Literal(Constant(paramRep))
    val paramRepExpr = c.Expr[String](paramRepTree)
    reify { println(paramRepExpr.splice + " = " + param.splice) }
  }
}

文字列でプロパティアクセスするマクロとかはこんな感じ。

import language.experimental.macros
import scala.reflect.macros.whitebox.Context

object AccesserMacro {
  def accesser(obj: Any, property: String): Any = macro impl

  def impl(c: Context)(obj: c.Expr[Any], property: c.Expr[String]) = {
    import c.universe._
    val Expr(Literal(Constant(propString: String))) =  property
    Select(obj.tree, TermName(propString))
  }
}

Def Macroのドキュメントにも書いてあるけどケースクラスの構造化代入使うと便利。

詳しいマクロやり方は、
http://docs.scala-lang.org/ja/overviews/macros/overview
を見つつScalaDocコメント読むのが良さそう。

StackOverFlowにマクロ職人が沢山いるので検索すると勉強になる。
http://stackoverflow.com/search?tab=votes&q=Scala%20macro

2.11でwhiteboxマクロとblackboxマクロというのが2.11で分かれていたので注意。
http://docs.scala-lang.org/ja/overviews/macros/blackbox-whitebox

1
0
0

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