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

Lai*_*uan 6 debugging scala compiler-directives scala-macros

在C++中我可以写:

#ifdef DEBUG
cout << "Debugging!" << endl;
Run Code Online (Sandbox Code Playgroud)

Scala中有没有相应的东西?

som*_*ytt 8

传统的习语是@elidable.

scaladoc涵盖了您的传统用例:

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


Ber*_*ium 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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

与...一起使用

import app.macros.log.{SimpleMacroLogger => log}

object SimpleMacroLoggerDemo extends App {
  log.info("Hello")
}
Run Code Online (Sandbox Code Playgroud)

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

如果设置,以虚假,宏完全消除记录.

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


And*_*yle 0

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

if (SystemProperties.get("debug.mode").exists(_ == "true") {
  println("Debugging!")
}
Run Code Online (Sandbox Code Playgroud)

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

object Constants {
    final val DEBUG = false
}

// ...

if (Constants.DEBUG) {
  println("Debugging!")
}
Run Code Online (Sandbox Code Playgroud)

  • `final val DEBUG` 或者它不是编译时常量。 (4认同)