Scalaのマクロを3分で知る

忙しい人のためにScala 2.1で取り入れられたマクロを3分で知るための手順を用意しました。

では時間もないので早速、新しい作業ディレクトリを作ってください。

新しく作った作業ディレクトリを以下の構成にしてください。
ファイルはgistのコードが下にあるのでそこからコピペで取ってきてください。

.
├── project
│   └── Build.scala
└── src
    └── logger
        ├── macro
        │   ├── Logger.scala
        │   └── LoggerMacros.scala
        └── main
            └── Main.scala
または、コピペも面倒だという人のためにバッチを用意しました。
以下のコマンドでディレクトリ作成からファイル作成まで完了させてください。
(!)作業用ディレクトリの下で以下のコマンドを実行してください。

curl -L https://gist.github.com/sndyuk/ab871010a7e77ddd6420/raw/027d93b3463006dca3d58fe8b928c7666b894940/install.sh | sh
コードの解説を簡単にしてあるので参考にしてください。




Logger.Scala
11行目のmacro ...はここでこのマクロを使うよという内容です。
他のコードはマクロと関係ないので無視して構いません。
LoggerMacros.scala 上のLogger.scalaが呼んでいるマクロです。
scala.reflect.macros.Contextを引数に受け取り、実行時に受け取る引数(この場合は、Stringmessageです)を受け取る関数を返す必要があります。
でも、ただのStringではなくContextExpr[T]型にラップされたものになります。実際この関数はマクロ展開時に呼ばれるのでただのStringは受け取れなくて当然ですね。
そしてこの関数の中で、展開後のコードを書いていきます。
Main.scala
マクロの動作を確認するためのコードです。
マクロ展開後のイメージ
マクロが展開されたMain.scalaはこんな感じになります。
Build.scala
いつものsbt用のBuild.scalaですが、マクロを先にコンパイルするためにmacroとmainの2プロジェクトを定義してあります。


用意ができた所で早速実行してみます。

実行結果
簡単に実行結果を説明すると、
sbtを起動してmainプロジェクトをコンパイルすると、mainプロジェクトはmacroプロジェクトに依存しているので、macroプロジェクトが先にコンパイルされ、その後に、mainプロジェクトがコンパイルされています。
(macroは事前にコンパイルされている必要があります)
コンソールに"Load macro"と2回出力されていることから、実際のコード上(Main.scala)で、2回loggerを呼んでいる箇所があり、その度にマクロが展開されていることがわかります。
そして、runでMain.scalaを実行すると正しくログ出力されていますね!

どうでしょう?Scalaのマクロの敷居が思ったより低く感じられたのではないでしょうか。

マクロの説明は公式にもありますので、さらに詳しく掘り下げて知りたいという方はリンク先から読むことをオススメします。

http://docs.scala-lang.org/overviews/macros/overview.html


Leave a Reply

Popular Posts