Reputation: 11559
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?
Upvotes: 6
Views: 1017
Reputation: 97178
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.
Upvotes: 7