Scala: Code only run when debugging(#ifdef equivalent?) - debugging

In C++ I can write:
#ifdef DEBUG
cout << "Debugging!" << endl;
Is there any equivalent in Scala?

The conventional idiom is #elidable.
The scaladoc covers your conventional use case:
http://www.scala-lang.org/api/current/scala/annotation/elidable.html

The equivalent form of a C preprocesser #ifdef is a Scala macro:
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
}
}
}
}
to be used with
import app.macros.log.{SimpleMacroLogger => log}
object SimpleMacroLoggerDemo extends App {
log.info("Hello")
}
It's far more complex to code, but it's usage is superior: There is no need for surrounding #ifdef/#endif etc. So it does not clutter up your code.
If you set on to false, the macro removes the logging completely.
Anything within the reify will go into the resulting byte code,
the other code is run at compile time. This especially applies to the if (on) ....

If you want the code to only be executed when certain conditions hold, you can use a standard if block:
if (SystemProperties.get("debug.mode").exists(_ == "true") {
println("Debugging!")
}
If you're concerned for whatever reason that the statement shouldn't even appear in the compiled output, then you can use an if-block with a compile-time constant expression. In these cases, javac/scalac will correctly infer that the condition will never be true, and so doesn't even include the bytecode for the block. (Obviously you'll need to modify your build to pull in a constant "true" for debug builds, and "false" for prod builds.)
object Constants {
final val DEBUG = false
}
// ...
if (Constants.DEBUG) {
println("Debugging!")
}

Related

How to suppress Kotlin unused parameter warning in all test classes?

In parameterized tests I use hint parameter to clarify test case naming. From the static analyzer point of view this parameter is never used, so this warning from kotlin-maven-plugin appears in the build log:
[WARNING] /Users/test/TestSizeCreation.kt: (42, 10) Parameter 'hint' is never used
How to suppress such warnings globally in all tests?
Example of test with hint:
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
assertThatThrownBy { Size(sizeCandidate) }
.isInstanceOf(InvalidInput::class.java)
.hasMessageStartingWith("Could not recognize size: ")
}
companion object {
#JvmStatic
fun invalidAges(): Stream<Arguments> =
Stream.of(
arguments("negative", -5),
arguments("zero", 0),
arguments("too much", 1000)
)
}
Two possible options (there may be more):
The first is to annotate the parameter as being unused, like this:
#Suppress("UNUSED_PARAMETER") either at the function or parameter level.
The second option is to use a lambda inside your test to execute the actual code, and then use an underscore to ignore the first parameter, like this:
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
class Stack {
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
process(hint, sizeCandidate) { _, size ->
println("add your test using size here $size")
}
}
private fun process(hint: String, sizeCandidate: Int, block: (String, Int) -> Unit) {
block(hint, sizeCandidate)
}
companion object {
#JvmStatic
fun invalidAges(): Stream<Arguments> =
Stream.of(
arguments("negative", -5),
arguments("zero", 0),
arguments("too much", 1000)
)
}
}
I ended up using this function introduced only in the src/test context:
// this function used only to avoid "Parameter is never used" warning
// on intentionally unused parameters
fun Any?.touch() = Unit
This how it looks in a test method:
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
hint.touch()
assertThatThrownBy { Size(sizeCandidate) }
.isInstanceOf(InvalidInput::class.java)
.hasMessageStartingWith("Could not recognize size: ")
}
Why:
The #Suppress("UNUSED_PARAMETER") is intended strictly for special situations in rare cases. And would be inappropriate to put it in all Parameterized tests making it noisy. It also could cause missing real cases of unused parameters, helping garbage code appear.
The touch method clearly shows intention. And it looks like a minimal evil.

Is CoroutineScope(SupervisorJob()) runs in Main scope?

I was doing this code lab
https://developer.android.com/codelabs/android-room-with-a-view-kotlin#13
and having a question
class WordsApplication : Application() {
// No need to cancel this scope as it'll be torn down with the process
val applicationScope = CoroutineScope(SupervisorJob())
// Using by lazy so the database and the repository are only created when they're needed
// rather than when the application starts
val database by lazy { WordRoomDatabase.getDatabase(this, applicationScope) }
val repository by lazy { WordRepository(database.wordDao()) }
}
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
var wordDao = database.wordDao()
// Delete all content here.
wordDao.deleteAll()
// Add sample words.
var word = Word("Hello")
wordDao.insert(word)
word = Word("World!")
wordDao.insert(word)
// TODO: Add your own words!
word = Word("TODO!")
wordDao.insert(word)
}
}
}
}
this is the code I found, as you can see, it is directly calling scope.launch(...)
my question is that:
isn't all the Room operations supposed to run in non-UI scope? Could someone help me to understand this? thanks so much!
Is CoroutineScope(SupervisorJob()) runs in Main scope?
No. By default CoroutineScope() uses Dispatchers.Default, as can be found in the documentation:
CoroutineScope() uses Dispatchers.Default for its coroutines.
isn't all the Room operations supposed to run in non-UI scope?
I'm not very familiar specifically with Room, but generally speaking it depends if the operation is suspending or blocking. You can run suspend functions from any dispatcher/thread. deleteAll() and insert() functions in the example are marked as suspend, therefore you can run them from both UI and non-UI threads.

CFor in Haxe using Macros

So, I love macros (yell at me).
I was trying to create a macro in Haxe, which allows me to write the traditional (C++, Java) for-loop and have the same functionality. But I am quite a beginner in Haxe...
Code:
import haxe.macro.Expr;
class Cfor {
macro public static function cfor(init: Expr, cond: Expr, post: Expr, body: Expr) {
return macro {
$init;
while ($cond) {
$body;
$post;
}
}
}
public static function main() {
trace("Traced");
cfor(var i = 0, i < 100, i++, {
var x = i * 2;
trace(x);
});
}
}
Questions:
It already works (that specific test), but it's not that close to the traditional for-loop. How to improve that?
Do you have any other improvements (style/functionality) for this code?
Is there anything target specific which I should know of about this code?
How can I see what this call to cfor expands to?
What about this?
https://gist.github.com/dpeek/7476625
The approach is different (applied to the context) but I think it is a little closer to the desired outcome.
I don't see any potential target specific issues with your code.

Is there any way to detect supported options in SDK

“Using SDK-Based Development” explains how to use weakly linked classes, methods, and functions ...
I have used this e.g.
if ([NSByteCountFormatter class]) {
...
}
Is there any way to detect supported options e.g.
NSRegularExpressionSearch
The search string is treated as an ICU-compatible regular expression.
If set, no other options can apply except NSCaseInsensitiveSearch and NSAnchoredSearch.
You can use this option only with the rangeOfString:... methods and stringByReplacingOccurrencesOfString:withString:options:range:.
Available in OS X v10.7 and later.
For testing whether a class, e.g. NSUserNotificationCenter, exists, do
if(NSClassFromString(#"NSUserNotificationCenter"))
{
//...
}
For testing whether a constant, e.g. NSWindowDidChangeBackingPropertiesNotification, exists, do
BOOL NSWindowDidChangeBackingPropertiesNotificationIsAvailable = (&NSWindowDidChangeBackingPropertiesNotification != NULL);
if (NSWindowDidChangeBackingPropertiesNotificationIsAvailable)
{
//...
}
Check out this answer also: Check if constant is defined at runtime in Obj-C
In your case, this looks like
BOOL NSRegularExpressionSearchIsAvailable = (&NSRegularExpressionSearch != NULL);
if (NSRegularExpressionSearchIsAvailable)
{
//...
}

Does GCC LTO perform cross-file dead code elimination?

Say I have a function
void do_something() {
//....
#ifdef FEATURE_X
feature_x();
#endif
//....
}
I can compile and run this with no problems; if I want the feature I can pass -D FEATURE_X and it works.
However, what if I would like to put do_something into another file (And not have to recompile that file as well each time I decide to change the option). If it was in the same file, I assume that
const int FEATURE_X=0;
void do_something() {
//....
if(FEATURE_X) {
feature_x();
}
//....
}
will use dead code elimination properly, eliminating the call. If I put this in another file, without LTO,
extern const int FEATURE_X;
void do_something() {
//....
if(FEATURE_X) {
feature_x();
}
//....
}
It will not remove the code (It has no way of knowing). So, with link time optimization enabled, can the compiler detect the value of FEATURE_X at link time, determine if the code is used or not, and remove it if appropriate?
GCC does cross module unreachable function removal, but it will not be able to determine the code is dead in your last testcase, because the constant value of FEATURE_X will be determined too late.
If you will use -D way or put your const int FEATURE_X=0; into every module then yes, the code will be eliminated.

Resources