Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to improve kotlin lambda syntax?

I'm trying to use kotlin M12 in android project and during the work I got this piece of code subscribe({onSuccess(it)}, {onFailure(it)})

AppObservable.bindActivity(this, api.get(id)).subscribe({onSuccess(it)}, {onFailure(it)})

fun onSuccess(str: String) {}

fun onFailure(tr: Throwable) {}

This is not so bad, but I think it would/should be better. How can I improve it?

like image 647
falcon Avatar asked Jul 01 '15 08:07

falcon


People also ask

Which is correct syntax for lambda?

The syntax of a lambda function is lambda args: expression . You first write the word lambda , then a single space, then a comma separated list of all the arguments, followed by a colon, and then the expression that is the body of the function.

How do you write lambda expression in Kotlin?

A lambda expression is always surrounded by curly braces, argument declarations go inside curly braces and have optional type annotations, the code_body goes after an arrow -> sign. If the inferred return type of the lambda is not Unit, then the last expression inside the lambda body is treated as return value.

Does Kotlin support lambda expressions?

You use lambda expressions extensively in Android development and more generally in Kotlin programming.

Is lambda faster than normal function?

Lambda functions are inline functions and thus execute comparatively faster.


1 Answers

First, create a helper extension method like this:

fun<T, R> Observable<T>.subscribe(
        receiver: R,
        onSuccess: R.(T) -> Unit, 
        onFailure: R.(Throwable) -> Unit) {
    subscribe({ receiver.onSuccess(it) }, { receiver.onFailure(it) })
}

Now you can use your new method like this:

AppObservable.bindActivity(this, api.get(id)).subscribe(this, ::onSuccess, ::onFailure)

The :: operator creates a method reference. Once KT-6947 gets resolved, we can omit the helper method and write subscribe(this::onSuccess, this::onFailure) directly. This is already possible in Java 8.

To work around this issue we can alternatively implement the following helper method that binds a receiver to an extension method:

fun <T, R, E> T.bind(reference: T.(R) -> E): (R) -> E = { this.reference(it) }

and use it like this:

AppObservable.bindActivity(this, api.get(id)).subscribe(bind(Foo::onSuccess), bind(Foo::onFailure))

but this is hardly more elegant than your initial solution.

EDIT1:

Thy syntax ::onSuccess is forbidden for now, so you have to use 'Foo::onSuccess' where Foo is your class name.

EDIT2:

You can have a little fun with operator overloading by declaring the same method as

operator fun <T, R, E> T.plus(reference: T.(R) -> E): (R) -> E = { this.reference(it) }

Then you can use it like so:

AppObservable.bindActivity(this, api.get(id)).subscribe(this + Foo::onSuccess, this + Foo::onFailure)
like image 199
Kirill Rakhman Avatar answered Oct 26 '22 14:10

Kirill Rakhman