Was looking at the benchmark code in the coroutine...
# coroutines
t
Was looking at the benchmark code in the coroutine project. Ran into this.
Copy code
fun concat(first: Flow<Int>, second: Flow<Int>): Flow<Int> = flow {
    first.collect { value ->
        return@collect emit(value)
    }

    second.collect { value ->
        return@collect emit(value)
    }
}
What is the point of the
return@collect
?
o
there is no void in kotlin so in java that looks something like:
Copy code
second.collect(value -> {
  return emit.invoke(value);
});
but if that was not added, it would be
Copy code
second.collect(value -> {
  emit.invoke(value);
  return Unit.INSTANCE;
});
which can potentially be less optimal I presume
t
so when I remove the
return@collect
it still works identically.
o
yes, it's still the same in theory
but I'm not a JVM optimization expert. for all I know this actually has a significant effect especially in the case of coroutines, I think it does because of the extra case where it returns
COROUTINE_SUSPENDED
. I recall seeing this kludge in the flow code somewhere, let me see if I can find it
t
is it shortcutting something? I saw stuff like that in the stdlib coroutine too
I recall something about tailrec in one I looked at
but this one doesn't seem like it's related
d
Are you talking about tail call optimisation?
t
yeah.. I saw something in the stdlib mentioning that w/ a similar looking return
and of course the relevant issue, https://youtrack.jetbrains.com/issue/KT-28938
t
yup.. That was it.
o
though it appears to have been fixed
t
awesome. So that's the same concept in that concat method I assume
o
yes
t
Awesome.. Thanks!
o
can confirm that on recent versions (1.3.61), this compiles the same https://gist.github.com/octylFractal/34ae00f1436d5391c7d427b74ab1850f
so that's unnecessary now
t
heh.. I just did the same thing. 🙂