Reputation: 4297
I'm currently learning kotlin and have came into the following scenario. In Ktor
server there's a method with the following signature:
fun Route.webSocket(protocol: String? = null, handler: suspend DefaultWebSocketServerSession.() -> Unit) {
webSocketRaw(protocol) {
proceedWebSocket(handler)
}
}
where I'm supposed to interact with it somehow like this:
embeddedServer(Netty, 8080) {
install(Routing) {
webSocket("/ws") {
// Handle websocket connection here
}
}
}
Meaning websocket accepts labda that's an extension method of DefaultWebSocketServerSession
and has it's context. I would like to convert this lambda into a handler so I can pass it from somewhere else, I imagine it should look something like that:
embeddedServer(Netty, 8080) {
install(Routing) {
webSocket("/ws", myHandler::handle)
}
}
//...
fun suspend handle(context: DefaultWebSocketServerSession): Unit {
// Handle websocket connection here
}
So, my question is how do I convert suspend DefaultWebSocketServerSession.() -> Unit
to(DefaultWebSocketServerSession) -> Unit
, or how do I Implement a handler with suspend DefaultWebSocketServerSession.() -> Unit
signature so I can pass it from the outside?
PS
I know I could do this
embeddedServer(Netty, 8080) {
install(Routing) {
webSocket("/ws") {
myHandler.handle(this)
}
}
}
But that doesn't feel elegant
Upvotes: 0
Views: 181
Reputation: 7788
There is no need to convert anything yourself. Kotlin converts between Method References, Function Literals and Function Literals with Receiver. Look at this example:
class A
class AHandler {
fun handle(a: A) {
println("AHandler $a")
}
}
fun useLambdaWithReceiver(lambda: A.()->Unit) {
val a = A()
lambda(a)
}
fun useNormalLambda(lambda: (A)->Unit) {
useLambdaWithReceiver(lambda)
}
fun main() {
val handler = AHandler()
useLambdaWithReceiver {
println("useLambdaWithReceiver $this")
}
useNormalLambda {
println("useNormalLambda $it")
}
useLambdaWithReceiver(handler::handle)
useNormalLambda(handler::handle)
}
Output:
useLambdaWithReceiver A@174d20a
useNormalLambda A@3c756e4d
AHandler A@2ef5e5e3
AHandler A@6d00a15d
Everything compiled and converted automatically.
So, you can just pass your handler method and it should be fine, unless there is a bug with suspend
modifier I am not aware of.
Upvotes: 2