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

Function expression without braces

Open voddan opened this issue 7 years ago • 6 comments

Do NOT use functional expression in the short function declaration form without curly braces.

// Good: full declaration form
fun(): Int { return 1 }

// Bad: short declaration form
fun() = 1
// Should be a lambda: 
{ 1 }

The short declaration for is almost never used for function expressions, and when it is, it easily leads to terrible unreadable code:

val test1 = fun(): Int = 42
fun test2(f: (Int) -> Boolean = fun(Int) = false) {}

test2(fun(Int) = true)
test2(f = fun(Int) = true)

Since the most common reason to use a function expression over a lambda is to get early returns, this rule should not affect production code, but it is worth it to have it in the formatter nevertheless.

voddan avatar Aug 13 '17 08:08 voddan

There are many reasons why you would want an expression without braces. We mainly use kotlin for tests and test factories. Kotlin allows us to have 'default values' for tests by using a style like this

    fun documentDescriptorAssociatedEvent(
            propertyId: PropertyId = PROPERTY_ID,
            appraisalId: AppraisalId = APPRAISAL_ID,
            loanTransactionId: LoanTransactionId = LOAN_TRANSACTION_ID,
            documentDescriptors: List<DocumentDescriptorId> = listOf(DOCUMENT_DESCRIPTOR_ID)
    ) = DocumentDescriptorAssociatedEvent(propertyId, appraisalId, loanTransactionId, documentDescriptors)

Note that this is a test factory, it's only purpose is to define default values for tests in the case that you don't want to provide values. Every single one of our test factory methods are only set to call a constructor. Adding in braces, a return type and a return makes that code at least 50% greater in length depending on how you format it (due to that line now overflowing the line length limit).

    fun documentDescriptorAssociatedEvent(
            propertyId: PropertyId = PROPERTY_ID,
            appraisalId: AppraisalId = APPRAISAL_ID,
            loanTransactionId: LoanTransactionId = LOAN_TRANSACTION_ID,
            documentDescriptors: List<DocumentDescriptorId> = listOf(DOCUMENT_DESCRIPTOR_ID)
    ) : DocumentDescriptorAssociatedEvent {
        return DocumentDescriptorAssociatedEvent(propertyId, appraisalId, loanTransactionId, 
                                                 documentDescriptors)
    }

snowe2010 avatar Oct 09 '17 15:10 snowe2010

I suggest the alternative

Do NOT use functional expression in the short function declaration form without curly braces, unless that function is used solely to call another function or to instantiate a singular object.

snowe2010 avatar Oct 09 '17 15:10 snowe2010

@snowe2010 I don't see a single function expression in your code snippets, only functions. Are you sure we are talking about the same thing?

voddan avatar Oct 09 '17 15:10 voddan

@voddan I think I am misunderstanding your suggestion then.

snowe2010 avatar Oct 09 '17 20:10 snowe2010

@snowe2010 A function expression is a special syntax for anonymous functions:

fun test(f: (Int) -> Int) {}

test({ x -> x + 1 })                 // a lambda expression
test(fun(x: Int){ return x + 1 } )   // a function expression
test(fun(x: Int) = x + 1 )           // same as above, but less useful and at times hard to read

voddan avatar Oct 09 '17 21:10 voddan

oh wow. ok, yes I was way off. I thought you were referring to functions bodies being created using = at times.

snowe2010 avatar Oct 09 '17 21:10 snowe2010