It would be really great to have something like ta...
# language-proposals
m
It would be really great to have something like takeUnless which allows you to include the element that fails the predicate:
Iterable<T>.takeUntil(pred: (T) -> Boolean)
or else, to make semantics more explicit, let’s add an optional parameter to takeUnless:
list.takeUnless(includeBreakingElement = true) { … }
or how about this:
list.takeUntilIncluding { … }
to that one we could also add an optional parameter indicating what should happen if no element matches. Callers could either want the entire list/stream returned, or an empty list (not possible for streams/sequences).
1
👍 7
d
I like the idea (which I used for my AoC day 8 solution), but couldn't settle on a good name.
until
usually means 'up to but not including' as in the open range (0 until 10) goes to 9. So you could have
takeTo
but that is weird.
takeUntil
which I ended up with for lack of a better name also needs to invert the predicate.
m
^ yes, which is why we should include the word “including” in whatever we introduce 🙂
d
Yes but I can't think of another function in the stdlib which I could compare it with, so a parameter might be okay here. This makes it comparable to something like windowed which has a parameter for partial windows
So of the options given, the 2nd one seems the best fit to me
r
I love how this channel suddenly sees so much more activity in december 😄 But yeah, I was crying too at my AoC code today I just cheated it via local variable with
takeWhile
&
onEach
combo on sequences, but that is ugly
j
kotlin stdlib maybe needs fewer oneliners? once its there it needs to be supported for basically ever. firstNotNullOfOrNull etc etc.
d
I'm not sure it needs fewer oneliners, I'm not sure how firstNotNullOfOrNull came to be, it just needs sensible oneliners. If we go with option 2, we would not even add a new function
m
Here’s a suggestion:
Copy code
private fun <T> Iterable<T>.takeUntilIncluding(p: (T) -> Boolean) = buildList {
    for (t in this@takeUntilIncluding) {
        add(t)
        if (p(t)) break
    }
}
I think that such one-liners should be added if they a) are quite generic and b) have the potential to be used and c) cannot easily be composed of other functional constructs which already exist. And d) are explicit and make intuitive sense and e) fit the general Kotlin idiomatic style 🙂
Another possible solution, maybe more clear:
Copy code
private fun <T> Iterable<T>.dropAfter(p: (T) -> Boolean) = buildList {
    for (t in this@dropAfter) {
        add(t)
        if (p(t)) break
    }
}
d
I think that one more clearly communicates the intent
m
We could have a nice pair of functions:
Copy code
private fun <T> Iterable<T>.dropAllAfter(p: (T) -> Boolean) = buildList {
    for (t in this@dropAllAfter) {
        add(t)
        if (p(t)) break
    }
}

private fun <T> Iterable<T>.takeAllBefore(p: (T) -> Boolean) = buildList {
    for (t in this@takeAllBefore) {
        if (p(t)) break
        add(t)
    }
}