https://kotlinlang.org logo
#coroutines
Title
# coroutines
r

Robert Jaros

03/29/2019, 5:52 PM
What is the easiest way to convert ReceiveChannel<T> to Channel<T> ?
o

octylFractal

03/29/2019, 5:55 PM
what do you mean by convert? you would need to add some sort of sending functionality, but it seems like an odd requirement
you could probably just create a new channel, and a new coroutine to copy between them, but there's nothing built in
r

Robert Jaros

03/29/2019, 6:00 PM
I need an object of type Channel<T> but I have ReceiveChannel<T>. I need to create a new object of type Channel<T> that will delegate receive to my ReceiveChannel and can throw an exception when send is called.
I hope it will work:
Copy code
val channel = Channel<T>()
launch {
    for (p in receiveChannel) channel.send(p)
}
u

uli

03/29/2019, 6:58 PM
Just do as you say,
Implementation by Delegation
https://kotlinlang.org/docs/reference/delegation.html And implement the remaining method to throw
r

Robert Jaros

03/29/2019, 8:07 PM
With delegation:
Copy code
val channel = object : Channel<T>, ReceiveChannel<T> by receiveChannel {
                @ExperimentalCoroutinesApi
                override val isClosedForSend: Boolean
                    get() = throw(UnsupportedOperationException())
                @ExperimentalCoroutinesApi
                override val isFull: Boolean
                    get() = throw(UnsupportedOperationException())
                override val onSend: SelectClause2<T, SendChannel<T>>
                    get() = throw(UnsupportedOperationException())

                override fun close(cause: Throwable?): Boolean {
                    throw(UnsupportedOperationException())
                }
                @ExperimentalCoroutinesApi
                override fun invokeOnClose(handler: (cause: Throwable?) -> Unit) {
                    throw(UnsupportedOperationException())
                }
                override fun offer(element: T): Boolean {
                    throw(UnsupportedOperationException())
                }
                override suspend fun send(element: T) {
                    throw(UnsupportedOperationException())
                }
            }
Which is better?
u

uli

03/29/2019, 9:28 PM
Well sure your initial suggestion is easier to read 😁 But it does not prevent the user of the Channel from doing funny stuff with the sender interface of the Channel. I also did not yet think about exception propagation of your first suggestion
d

Dico

03/30/2019, 9:11 AM
What is your use case? This is almost certainly improper use of the API.
If you have 2 separate channel endpoints that are not related, why are you trying to wrap them into one reference
Have a
sendChannel
and a
receiveChannel
and pass both to the part of your code that currently expects a
Channel
.
Channel
is only used when both endpoints are connected, in other words, when the
send
function sends elements to the
receive
function of the same
Channel
reference.
r

Robert Jaros

03/30/2019, 11:36 AM
In the meantime, I have actually changed my code and this issue is no longer relevant. But it was still fun to think about it 😉
7 Views