What does the @elidable annotation do in Scala, and when should I use it?

前端 未结 3 538
鱼传尺愫
鱼传尺愫 2021-02-05 05:09

I\'ve noticed in some of the scala library code, notably Predef, there is code like:

/** Tests an expression, throwing an `AssertionError` if false.         


        
3条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-05 05:17

    As a complement to Tomasz Nurkiewicz's answer two comments.

    (1) C++ style

    Because I came from C++ I've defined

    /** ''Switch'' between '''Debug''' and '''Release''' version. */
    object BuildLevel {
      type only = annotation.elidable
      final val DEBUG = annotation.elidable.INFO
    }
    

    and use this in good old C++ preprocessor style like

    import BuildLevel._
    @only(DEBUG)
    private def checkExpensive(...) {
      ...
    }
    
    override def compare(that: ): Int = {
      checkExpensive(...)
      ...
    }
    

    to mark expensive checks (check of pre-conditions or invariants that must always holds true) that I want to switch off in release builds.

    Of course that's just similar to the assert use case except for the difference of refactoring out expensive code in a separate method that should be switched off as a whole. But all this is only worthwhile for really expensive checks. In a 10k lines project I have only 3 marked checks. Cheaper tests I wouldn't switch off and leave in the code, because they increase its robustness.

    (2) Unit signature

    This approach is suitable only for methods with a (...) => Unit signature. If one use a result of such a switched off method like

    @only(DEBUG)
    def checkExpensive(that: Any): Int = {
      4
    }
    val n = checkExpensive(this)
    

    at least my Scala 2.9.1.final compiler crashes. However, there is not much sense in such a signature. Because: Which value should such a switched off method return?

提交回复
热议问题