Skip to content
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

proposal: x/exp/xiter: add {Drop,Take}{,While}{,2} #67442

Open
jimmyfrasche opened this issue May 16, 2024 · 4 comments
Open

proposal: x/exp/xiter: add {Drop,Take}{,While}{,2} #67442

jimmyfrasche opened this issue May 16, 2024 · 4 comments
Labels
Milestone

Comments

@jimmyfrasche
Copy link
Member

Add

func Drop[K any](int, iter.Seq[K]) iter.Seq[K]

func DropWhile[K any](func(K) bool, iter.Seq[K]) iter.Seq[K]

func Take[K any](int, iter.Seq[K]) iter.Seq[K]

func TakeWhile[K any](func(K) bool, iter.Seq[K]) iter.Seq[K]

(and similarly for the iter.Seq2 variants) to x/exp/xiter.

t := Take(n, seq) returns an iterator t that takes up to the first n results of seq. If seq yields m values than the iterator t yields min(m, n) values.

TakeWhile(pred, seq) is similar to Take except instead of taking a set number of values it yields while pred returns true.

Drop(n, seq) skips the first n results of seq. DropWhile similarly skips results while its predicate evaluates to true.


Note that Take{,2} is Limit{,2} in #61898. This proposal thus includes renaming that.

These names and functions are standard across all languages I checked (Python, Haskell, OCaml, Scheme). I had originally proposed these as LimitFunc{,2} and Skip{,Func}{,2} to go with Limit but decided to stick with the common names in this proposal.

While there is an argument to be made that TakeFunc etc. would be more in line with Go naming, but, in addition, to bucking the trend from other languages' libraries that doesn't say which way the predicate is used whereas While makes it clear.

Here is a link with basic examples and implementations https://go.dev/play/p/DQhz7X_95wf?v=gotip

@leaxoy
Copy link

leaxoy commented May 17, 2024

Also Step ?

@ianlancetaylor ianlancetaylor moved this to Incoming in Proposals May 18, 2024
@jimmyfrasche
Copy link
Member Author

Step is far less commonly defined in iter libraries and I've not needed it so I'm not really sure of the use cases. Where does it come up?

@leaxoy
Copy link

leaxoy commented May 19, 2024

Imagine there is a range sequence, let’s think it is implemented like this:

func Range(start, stop int) func(yield func(int) bool) {
    return func(yield func(int) bool) {
        for x := start; x < stop; x++{
            if !yield(x) {
                return
            }
        }
    }
}

So Step can used like this:

func x() {
    for i := range Step(Range(0, 10), 3) {
        print(i)
        // produce 0, 3, 6, 9
    }
}

@jimmyfrasche
Copy link
Member Author

I understand how to use it not when it would be useful to use.

The Take functions are useful for taking an iterator of unbounded length and providing a stopping condition. It often simplifies both to separate the generate and stop-generating logic, especially since the latter is often involved and specific to a situation.

The Drop functions are useful when you don't need to handle the input until some condition or threshold is passed.

Step only really seems useful for numeric sequences like and even then I can't really think of uses other than what you wrote. Is there a case where you couldn't just put that in the generator? Is there a nonnumeric use case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

No branches or pull requests

2 participants