-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Add ReceiveChannel.toList(destination) #4520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Use case: collecting elements up until the point the channel is closed without losing the elements when `toList` when the exception is thrown. This function is similar to `Flow<T>.toList(destination)`, which we already have, so the addition makes sense from the point of view of consistency as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context, Flow's toList(destination) that you've referenced
} | ||
} | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re the original toList() docmuentation - shall it say that toList must be used by a single consumer (the implication of consumeEach and the iterator used there)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It already says so:
- The operation is terminal.
- This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but the UX is bad and in its current form people will use it incorrectly with a higher probability.
Terminal doesn't redirect anywhere.
Oh wait, you can technically call it from different coroutines, it just doesn't make much sense. Nevermind then.
63b1e1a
to
2d8f52b
Compare
add(it) | ||
} | ||
} | ||
public suspend inline fun <T> ReceiveChannel<T>.toList(destination: MutableList<T> = ArrayList()): List<T> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, we can't check that the return value will be used now. Maybe unsplit it back, and do not return List on one of the destination overload?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've attempted this, but cross-referencing overloads clutters the documentation quite a bit, and also, Flow.toList
already follows the single-overload approach: public suspend fun <T> Flow<T>.toList(destination: MutableList<T> = ArrayList()): List<T>
, so it's more internally consistent to have a single overload.
I'm wondering how real the risk of calling toList()
on a channel and forgetting to obtain the resulting list is. Do you have an opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could in theory check it on flow
if people do this mistake...
However, having the return value also allows chaining, and that tips the scale for me.
So let's keep your current version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if people mistakenly do flow.toList()
instead of flow.collect()
to trigger flow execution for its side effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sandwwraith, what do you think, is it more idiomatic to have fun X.toList(): List<T>
+ fun X.toList(destination: MutableList<T>): Unit
or just fun X.toList(destination: MutableList<T> = ArrayList<T>): List<T>
from the point of view of having an excessive return value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to have it as in the stdlib now: fun X.toList(): List<T>
+ @Ignorable fun <C: Collection/MutableList> X.toCollection/MutableList(destination: C): C
. Generic argument in the second function allows you to collect result to ArrayList
or HashSet
, for example.
} | ||
|
||
@Deprecated("Preserving binary compatibility, was stable", level = DeprecationLevel.HIDDEN) | ||
public suspend fun <T> ReceiveChannel<T>.toList(): List<T> = toList(ArrayList()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline police
4992f06
to
aa1adf1
Compare
aa1adf1
to
6039cf8
Compare
Use case: collecting elements up until the point the channel is closed without losing the elements when
toList
when the exception is thrown.This function is similar to
Flow<T>.toList(destination)
, which we already have, so the addition makes sense from the point of view of consistency as well.