Is there a better way to write this: ```val CJK_EX...
# stdlib
m
Is there a better way to write this:
Copy code
val CJK_EXTENSIONS_STR = fun (): String {
    var result = "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_A}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_B}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_C}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_D}"
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        result += "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            result += "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}"
        }
    }
    return result
}.invoke()
1
m
Firstly, you can use
run
instead of
fun {}.invoke()
.
👍 1
m
Ah yes of course:
Copy code
val CJK_EXTENSIONS_STR = run {
    var result = "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_A}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_B}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_C}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_D}"
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        result += "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            result += "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}"
        }
    }
    result
}
m
And then if you want to get rid of the
var
, you could do something like this:
Copy code
result +        "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}".takeIf { Build.VERSION.SDK_INT >= Build.VERSION_CODES.N }.orEmpty() +         "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}".takeIf { Build.VERSION.SDK_INT >= Build.VERSION_CODES.P }.orEmpty()
Up to you if you think that's more readable 😛
m
Thanks, I didn’t know about `orEmpty()`: super useful!
How about:
Copy code
val CJK_EXTENSIONS_STR = run {
    StringBuilder("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_A}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_B}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_C}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_D}").apply {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            append("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                append("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}")
            }
        }
    }.toString()
}
m
Right, and since that is now just a single expression, you don't even need
run
anymore.
m
Not bad, but do I need to worry (performance-wise) about creating the builder?
Copy code
val CJK_EXTENSIONS_STR = StringBuilder("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_A}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_B}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_C}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_D}").apply {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        append("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            append("\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}")
        }
    }
}.toString()
m
No, it's good. But the compiled code will use
StringBuilder
if you use
+
as well.
👍 1
m
Do you mean it will compile to pretty much the same code vs. using
var result
?
m
It will compile to pretty much the same code as you have in your latest example.
👍 1
At least for continous chains of
+
operations. If there are loops involved, then you should use the
StringBuilder
explicitly.
m
In terms of readability, i quite like:
Copy code
val CJK_EXTENSIONS_STR = "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_A}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_B}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_C}\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_D}"
        .appendIf(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N, "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_E}")
        .appendIf(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P, "\\p{InCJK_UNIFIED_IDEOGRAPHS_EXTENSION_F}")

fun String.appendIf(appendIt: Boolean, text: String) = if (appendIt) {
    this + text
} else {
    this
}