Scala:代码仅在调试时运行(#ifdef等效?)

时间:2013-05-29 16:42:58

标签: debugging scala compiler-directives scala-macros

在C ++中我可以写:

#ifdef DEBUG
cout << "Debugging!" << endl;

Scala中是否有任何等效内容?

3 个答案:

答案 0 :(得分:7)

C preprocesser #ifdef 的等效形式是 Scala宏

package app.macros.log

import scala.language.experimental.macros

import reflect.macros.Context

object SimpleMacroLogger {
  private val on = true

  def info(msg: String): Unit = macro info_impl

  def info_impl(c: Context)(msg: c.Expr[String]): c.Expr[Unit] = {
    import c.universe._

    if (on) {
      reify {
        println(msg.splice)
      }
    } else {
      reify {
        // Nothing
      }
    }
  }
}

一起使用
import app.macros.log.{SimpleMacroLogger => log}

object SimpleMacroLoggerDemo extends App {
  log.info("Hello")
}

代码要复杂得多,但它的用法更优越:不需要包含#ifdef /#endif等。所以它不会使你的代码混乱。

如果您将 on 设置为 false ,则宏会完全删除日志记录。

reify中的任何内容都将进入生成的字节代码, 其他代码在编译时运行。这尤其适用于 if(on)...

答案 1 :(得分:7)

传统的习语是@elidable。

scaladoc涵盖了您的传统用例:

http://www.scala-lang.org/api/current/scala/annotation/elidable.html

答案 2 :(得分:-1)

如果您希望代码仅在某些条件成立时执行,您可以使用标准if块:

if (SystemProperties.get("debug.mode").exists(_ == "true") {
  println("Debugging!")
}

如果您担心该语句甚至不应出现在编译输出中,那么您可以使用带有编译时常量表达式的if-block。在这些情况下,javac / scalac将正确地推断条件永远不会为真,因此甚至不包括块的字节码。 (显然,您需要修改构建以为调试版本提供常量“true”,并为prod构建提供“false”。)

object Constants {
    final val DEBUG = false
}

// ...

if (Constants.DEBUG) {
  println("Debugging!")
}