Both method and all calls to it simply disappear. This might be a good idea to use for logging since every logging framework introduces some overhead when logging is called but a given level is disabled (computing the effective level and preparing arguments).
Short answer Both method and all calls to it simply disappear. This might be a good idea to use for logging since every logging framework introduces some overhead when logging is called but a given level is disabled (computing the effective level and preparing arguments). Note that modern logging frameworks try to reduce this footprint as much as possible (e.g. Logback optimizes is*Enabled() calls and SLF4S passes message by name to avoid unnecessary string concatenations).
Long one My test code: import scala.annotation. Elidable import scala.annotation.elidable. _ class Foobar { info() warning() @elidable(INFO) def info() {println("INFO")} @elidable(WARNING) def warning() {println("WARNING")} } Proves that with -Xelide-below 800 both statements are printed while with 900 only "WARNING" appears.
So what happens under the hood? $ scalac -Xelide-below 800 Foobar. Scala && javap -c Foobar public class Foobar extends java.lang.
Object implements scala. ScalaObject{ public void info(); //... public void warning(); //... public Foobar(); Code: 0: aload_0 1: invokespecial #26; //Method java/lang/Object."":()V 4: aload_0 5: invokevirtual #30; //Method info:()V 8: aload_0 9: invokevirtual #32; //Method warning:()V 12: return } As you can see this compiles normally. However when this instruction is used: $ scalac -Xelide-below 900 Foobar.
Scala && javap -c Foobar calls to info() and the method itself disappears from the bytecode: public class Foobar extends java.lang. Object implements scala. ScalaObject{ public void warning(); //... public Foobar(); Code: 0: aload_0 1: invokespecial #23; //Method java/lang/Object.
"":()V 4: aload_0 5: invokevirtual #27; //Method warning:()V 8: return } I would expect that NoSuchMethodError is thrown at runtime when removed method is called from client code compiled against Foobar version with lower elide-below threshold . Also it smells like good old C preprocessor, and as such I would think twice before employing @elidable.
1 for thinking twice! – dave Dec 5 '11 at 18:34.
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?
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.