Scala:代码仅在调试时运行(#ifdef 等效?)
Posted
技术标签:
【中文标题】Scala:代码仅在调试时运行(#ifdef 等效?)【英文标题】:Scala: Code only run when debugging(#ifdef equivalent?) 【发布时间】:2013-05-29 16:42:58 【问题描述】:我可以用 C++ 编写:
#ifdef DEBUG
cout << "Debugging!" << endl;
Scala 中是否有任何等价物?
【问题讨论】:
Debug log in Scala with no performance impact的可能重复 顺便说一句,JVM 和它的 JIT 通常在消除死代码方面做得很好,因此很可能简单的final val DEBUG = false
和 def log(str: String) = if (DEBUG) print(str)
在大多数情况下就足够了。
【参考方案1】:
传统的成语是@elidable。
scaladoc 涵盖了您的常规用例:
http://www.scala-lang.org/api/current/scala/annotation/elidable.html
【讨论】:
除了在 Predef.assert 中间接使用之外,可能没有人使用 elidable,但实际上从未删除任何东西。如评论中所述,if (DEBUG)
标志为 final val
(仅限推断类型)或 val DEBUG: true = true
保证简单消除。【参考方案2】:
C 预处理器#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) ...。
【讨论】:
【参考方案3】:如果您希望代码仅在某些条件成立时执行,您可以使用标准 if 块:
if (SystemProperties.get("debug.mode").exists(_ == "true")
println("Debugging!")
如果您出于某种原因担心该语句甚至不应该出现在编译输出中,那么您可以使用带有编译时常量表达式的 if 块。在这些情况下,javac/scalac 将正确推断条件永远不会为真,因此甚至不包括块的字节码。 (显然你需要修改你的构建,为调试构建引入一个常量“true”,为 prod 构建引入一个常量“false”。)
object Constants
final val DEBUG = false
// ...
if (Constants.DEBUG)
println("Debugging!")
【讨论】:
final val DEBUG
或者它不是编译时常量。以上是关于Scala:代码仅在调试时运行(#ifdef 等效?)的主要内容,如果未能解决你的问题,请参考以下文章