Stylianos Gakis
04/25/2022, 1:31 PMfun foo(lambda: Bar.() -> Unit)
. On one of the places where I call this, I happen to be inside a suspending function, where I want to be able to simply call on a suspend function like I normally would. This isn’t allowed since that lambda isn’t suspending, and I can’t make it suspending either. I see that this is solved in the vast majority of cases by having the function itself be inline
which makes this possible, however I see that it’s not possible to define an interface function as inline.
I’m sure this is something that others have faced as well, what are my options? I see that this is solved by defining them as extension functions to the interface like map is defined, but in my case I can’t do that either since the implementation of my interface wants to use some local variables when implementing this function.Joffrey
04/25/2022, 1:35 PMfoo
as inline
in the first place. If it's not called in-place, then it doesn't matter whether you're calling foo
from a suspend function or not, what matters is the caller of the lambda itself - it may rely on the fact that this lambda is called synchronously, blocking the thread. In that case you have no choice but to block in order to call your suspend function (e.g. using runBlocking { ... }
, provided you're not on JS platform).ephemient
04/25/2022, 1:36 PMsuspend fun foo(lambda: suspend Bar.() -> Unit)
or an inline foo
if you want it to be callable with a suspending lambda. those are your options.Stylianos Gakis
04/25/2022, 1:44 PMfoo
as you say, but that’s specifically when I meet the 'inline' modifier is not allowed on virtual members. Only private or final members can be inlined
problem, and the IDE hint is to extract it as an extension function, which as I said before I can’t quite do since my implementation uses local values which I wouldn’t have access to in the extension function.
I see that both of you suggest that foo should be inline in the first place, am I missing something that I’d need to do to not have the error that I mention above?Joffrey
04/25/2022, 1:53 PMinline
not being possible in an interface. Yeah the compiler cannot know what to inline without knowing the implementation up front, and the point of a virtual method is to not know the implementation up front.
my implementation uses local values which I wouldn’t have access to in the extension functionI thought you meant local variables (which are definitely ok in extension functions), but you're talking about private fields here, which indeed is a burden. One option is to provide a public API for the operations you want to do before and after calling the lambda, so you can use an inline extension function. Another option would be to provide a
suspend
overload of your function (probably with a different name) which you can call when you need your lambda to be suspending:
interface IFoo {
fun foo(lambda: String.() -> Unit)
suspend fun fooSuspend(lambda: suspend String.() -> Unit)
}
Joffrey
04/25/2022, 1:59 PMStylianos Gakis
04/25/2022, 2:00 PMStylianos Gakis
04/25/2022, 2:01 PM