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 = falsedef 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 等效?)的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 代码仅在调试时运行

编译器指令 - 建议 - 仅在调试模式下运行代码

仅在调试代码时出现进程中的 hsqldb 错误

Visual Studio c++ 仅在调试模式下 LNK 1104 错误

导入 PySide2 时 DLL 加载失败,仅在调试时

C++ VS 调试代码,设置你自己的调试标志