Search code examples
javakotlinfuturecompletable-future

Kotlin Lambda function as a parameter


I am new to Kotlin and have difficulty understand the code below

private fun <T> catchAsyncExceptions(f: () -> CompletableFuture<T>) =
    try {
        f().get()
    } catch (e: ExecutionException) {
        throw e.cause!!
    }

So this function is called catchAsyncExceptions, its input parameter is a function called f which is () -> CompletableFuture<T> So I would think that you use it by

catchAsyncExceptions(someFunctionThatTakesNoArgumentAndReturnsCompletableFuture)

However I see the usage is

override fun getUserInfo(userId: String) =
    catchAsyncExceptions {
        membersClient.getUserLocation(
            GetUserLocationRequest(userId)
        )
            .thenApply { response ->
                val (success, error) = parseSuccessAndError<GetUserLocationResponseResult.Success>(response.result!!)
                error?.let {
                    UserInfoResponse(
                        error = error.code
                        )
                    )
                } ?: run {
                    UserInfoResponse(
                        data = UserInfoResponseDto(
                            location = success?.success?.location.toString(),
                        )
                    )
                }
            }
    }

Note that

membersClient.getUserLocation(
            GetUserLocationRequest(userId)
        )

returns CompletableFuture type

I am especially confused why it was a curly bracket rather than a bracket

catchAsyncExceptions {
...
}

Solution

  • In Kotlin, when you have a lambda function as a parameter, the brackets are completely optional. You can rewrite the implementation as:

    catchAsyncExceptions({
        membersClient.getUserLocation(
            GetUserLocationRequest(userId)
        )
            .thenApply({ response ->
                val (success, error) = parseSuccessAndError<GetUserLocationResponseResult.Success>(response.result!!)
                error?.let({
                    UserInfoResponse(
                        error = error.code
                        )
                    )
                }) ?: run({
                    UserInfoResponse(
                        data = UserInfoResponseDto(
                            location = success?.success?.location.toString(),
                        )
                    )
                })
            })
    })
    

    and this is a perfectly working code. For simplicity, the brackets are omitted to make the code more readable.