I was having some issues using RxJava and Kotlin earlier. I made some interesting discoveries which I'm still puzzled about.
There is the simple Func1
interface in RxJava
public interface Func1<T, R> extends Function {
R call(T t);
}
I was trying to add an extension method to an Observable
, also an RxJava class. This would collect the emissions into a Google Guava ImmutableListMulitmap
using a Func1
to map the key off each item.
fun <K,T> Observable<T>.toImmutableListMultimap(keyMapper: Func1<T, K>): Observable<ImmutableListMultimap<K,T>> {
return this.collect({ ImmutableListMultimap.builder<K,T>()},{ b, t -> b.put(keyMapper.call(t), t)}).map { it.build() }
}
When I tried to invoke this extension method I could not get it to compile, and it was not understanding the lambda expression at all.
ScheduledItem.all.flatMap { it.rebuildSoftTransactions }
.toImmutableListMultimap { it.id /*compile error */ } .cache()
However, the strangest thing happened when I modified the extension method to use the function type.
fun <K,T> Observable<T>.toImmutableListMultimap(keyMapper: (T) -> K): Observable<ImmutableListMultimap<K,T>> {
return this.collect({ ImmutableListMultimap.builder<K,T>()},{ b, t -> b.put(keyMapper(t), t)}).map { it.build() }
}
And then everything compiled fine. But this is what puzzled me: How come it did not infer the lambda onto the interface? When I use the standard map()
method on the Observable
it infers the lambda just fine using the curly bracket { }
syntax. But why does it not work for my extension method above?
The SAM conversion (converting a lambda into a function type) currently works only for methods written in Java. Kotlin has proper function types, so there is no need for SAM conversion - you can declare the parameter as a function type directly (which works, as you have observed).
Observable.map()
is written in Java, so the SAM conversion is applied. Your extension function is written in Kotlin, so it's not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With