Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested let blocks in Kotlin

Tags:

android

kotlin

Is it a good practice to use multiple nested let in Kotlin or should I introduce a local variable instead? Is there any overhead?

webView?.let { webview ->
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        webview.setLayerType(View.LAYER_TYPE_HARDWARE, null)
    } else {
        webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
    }

    webview.webViewClient = WebViewClient()

    webview.settings.let { settings ->
        settings.javaScriptEnabled = true
        settings.setSupportZoom(false)
        settings.builtInZoomControls = false
        settings.displayZoomControls = false
        settings.loadsImagesAutomatically = true
    }
}
like image 281
Sparrow318 Avatar asked Feb 16 '18 13:02

Sparrow318


4 Answers

Since let is inlined (see: what is inlining, also the official docs), its cost is the exact same as declaring the local variable yourself. If you're using it with a safe call, it also adds a null check, which you'd have to do manually as well.

So there's basically no overhead to using it, feel free to use it as much as you want as long as your code is legible enough for you.


For example, code like this:

webview.settings.let { settings ->
    settings.javaScriptEnabled = true
    settings.setSupportZoom(false)
}

... would roughly translate to bytecode equivalent to this Java code:

Settings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(false);

Except settings would probably be called something generic like var10000, but that's besides the point. Point is that no function instances are created and no let function is called or anything like that, therefore no overhead.

For any future concerns, you can actually check this yourself by using the Kotlin plugin's bytecode viewer and decompiler.

like image 170
zsmb13 Avatar answered Oct 24 '22 03:10

zsmb13


Kotlin's creators recommend not to use too many nested let calls to achieve better code readability and conciseness. In their book 'Kotlin in Action' they say

When you need to check multiple values for null, you can use nested let calls to handle them. But in most cases, such code ends up fairly verbose and hard to follow. It’s generally easier to use a regular if expression to check all the values together.

like image 43
Yogesh Umesh Vaity Avatar answered Oct 24 '22 01:10

Yogesh Umesh Vaity


A side remark. The inner let block could be rewritten for better readability with run:

webview.settings.run {
    javaScriptEnabled = true
    setSupportZoom(false)
    builtInZoomControls = false
    displayZoomControls = false
    loadsImagesAutomatically = true
}
like image 1
Inego Avatar answered Oct 24 '22 02:10

Inego


As an addition to zmbs13's answer:

Since you don't need a null check for webview.settings, it would be better to use apply which takes a lambda with receiver:

webview.settings.apply {
    // you refer to webview.settings with 'this', which can be omitted
    this.javaScriptEnabled = true // using this explicitely, in case there is another variable 'javaScriptEnabled' in this block
    setSupportZoom(false) // omitting this from here on
    builtInZoomControls = false
    displayZoomControls = false
    loadsImagesAutomatically = true
}

This makes your code even more concise and avoids the redundancy of having to write settings, or it multiple times.

like image 1
Willi Mentzel Avatar answered Oct 24 '22 01:10

Willi Mentzel