kotlin-style-guide icon indicating copy to clipboard operation
kotlin-style-guide copied to clipboard

Using conditional statements

Open yole opened this issue 9 years ago • 11 comments
trafficstars

Prefer using the expression form of try, if and when. Example:

return if (x) foo() else bar()

The above is preferable to:

if (x)
    return foo()
else
    return bar()

Prefer using if for binary conditions instead of when. Instead of

when(x) {
    null -> ...
    else -> ...  
}

use if (x == null) ... else ...

If the branches of an if statement are single expressions but don't both fit on the same line, indent the expressions by two levels (8 spaces) and the else keyword by one level (4 spaces):

val x = if (foo)
        longExpressionOne()
    else
        longExpressionTwo()        

In a when statement, if a branch is more than a single line, always separate it from adjacent case blocks with a blank line:

private fun parsePropertyValue(propName: String, token: Token) {
    when (token) {
        is Token.ValueToken ->
            callback.visitValue(propName, token.value)

        Token.LBRACE -> { // ...
        }

Put short branches on the same line as the condition, without braces.

when(foo) {
    true -> bar() //good
    false -> { baz() } //bad
}

yole avatar May 31 '16 18:05 yole

To me, the name of the issue is not very clear. Which statements exactly are meant?

I think loops deserve a separate issue where the pros and cons as well as use cases can be discussed. For example, you can use forEach with the safe-call operator. Related SO questions: http://stackoverflow.com/questions/34642868/how-do-i-do-a-break-or-continue-when-in-a-functional-loop-within-kotlin http://stackoverflow.com/questions/34703867/how-to-continue-or-break-in-a-when-statement-inside-a-while-loop-using-k

Is using braces for when branches in scope for this issue? If yes, I would suggest not using braces for single statements.

when(foo) {
    true -> bar() //good
    false -> { baz() } //bad
}

cypressious avatar Jun 01 '16 14:06 cypressious

Prefer using if for binary conditions instead of when.

This is not appropriate IMO:

when(boo) {
    true -> ...
    false -> ...
}

or

when(x) {
    null -> ...
    else -> ...
}

An additional issue with excessive use of when is that people may think that when is an analog of Scala's match case and is necessary for the smart cast to work, while in fact if provides exactly the same capabilities.

I heard about this misconception from a guy who read the 5th example in the docs section:

val hasPrefix = when(x) {
  is String -> x.startsWith("prefix")
  else -> false
}

This is looks much better using if:

val hasPrefix = if(x is String) x.startsWith("prefix") else false

voddan avatar Jun 08 '16 08:06 voddan

For me one of the most contentious issues is how to format if expression with moderately long single expression branches, like this

val scope = if (includeNonProjectItems)
    GlobalSearchScope.allScope(project)
else
    GlobalSearchScope.projectScope(project)

This zig-zag shape look ugly to me.

Placing this all on the single line does not work, the line is way too long:

val scope = if (includeNonProjectItems) GlobalSearchScope.allScope(project) else GlobalSearchScope.projectScope(project)

Something like this is probably better, but is not very symmetric:

val scope = if (includeNonProjectItems)
    GlobalSearchScope.allScope(project)
    else GlobalSearchScope.projectScope(project)

And, most surprisingly, when has just the right lovely oval shape here

val scope = when (includeNonProjectItems) {
    true -> GlobalSearchScope.allScope(project)
    else -> GlobalSearchScope.projectScope(project)
}

but is still ugly because it is a when and not an if.

matklad avatar Jun 10 '16 12:06 matklad

You can use the other when syntax:

val scope = when {
    includeNonProjectItems -> GlobalSearchScope.allScope(project)
    else -> GlobalSearchScope.projectScope(project)
}

cypressious avatar Jun 10 '16 12:06 cypressious

This is looks much better using if:

@voddan And even better not using if :)

val hasPrefix = x is String && x.startsWith("prefix")

matklad avatar Jun 10 '16 12:06 matklad

@matklad in your example withif the indentation should highlight the value assignment, IMO:

val scope = if (includeNonProjectItems)
        GlobalSearchScope.allScope(project)
    else
        GlobalSearchScope.projectScope(project)

voddan avatar Jun 10 '16 14:06 voddan

Another options is to indent everything to full alignment:

val scope = if (includeNonProjectItems)
               GlobalSearchScope.allScope(project)
            else
               GlobalSearchScope.projectScope(project)

yole avatar Jun 12 '16 08:06 yole

@yole I like that ^^. The rule is if and else are on the same indentation level. Not sure how it plays with #1 in case of an if-else multiline expression

voddan avatar Jun 12 '16 08:06 voddan

Will this work?

val scope = 
        if (includeNonProjectItems)
            GlobalSearchScope.allScope(project)
        else
            GlobalSearchScope.projectScope(project)

curioustechizen avatar Mar 09 '17 13:03 curioustechizen

When I have a very long if-else, I format it this way:

val scope = 
     if (includeNonProjectItems) GlobalSearchScope.allScope(project)
     else GlobalSearchScope.projectScope(project)

MarcinMoskala avatar Feb 15 '19 15:02 MarcinMoskala

You can use the other when syntax:

val scope = when {
    includeNonProjectItems -> GlobalSearchScope.allScope(project)
    else -> GlobalSearchScope.projectScope(project)
}

What's the opinion about this? I prefer using this instead of an if else branch.

mgoyanes avatar May 30 '20 17:05 mgoyanes