[swift-evolution] [Review] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

Kevin Ballard kevin at sb.org
Wed May 25 15:18:32 CDT 2016


On Wed, May 25, 2016, at 01:08 PM, Dave Abrahams wrote:
> 
> 
> 
> On behalf of Dmitri Gribenko, Max Moiseev, and myself:
> 
> on Thu May 19 2016, Kevin Ballard <swift-evolution-m3FHrko0VLzYtjvyW6yDsg at public.gmane.org> wrote:
> 
> > After having given this some thought, it seems apparent that `sequence
> > (state:next:)` is equivalent to `AnyIterator({ ... })` where the closure
> > captures a single mutable variable. 
> 
> Yes.  
> 
> > The microbenchmark performance may differ slightly, as the AnyIterator
> > version will allocate a box on the heap to hold the captured variable
> > (assuming it can't get inlined entirely), whereas UnfoldSequence
> > won't. But the functionality is the same.  Thus the question: do we
> > want to keep `sequence(state:next:)` or is it too close to AnyIterator
> > in functionality? 
> 
> We think the need to do a capture is icky, so the sequence form is
> almost always better.

I agree that the need for a capture is ugly.

> > Arguments in favor of `sequence(state:next:)`: *
> > It's equivalent to unfold and the dual of reduce, so people who've
> > used functional programming languages may expect it to exist.  * It
> > allows you to create ad-hoc stateful sequences without polluting the
> > current scope with a variable that exists solely to be captured.  * If
> > the cost of a small heap allocation is significant for your code, it
> > may be more performant than AnyIterator.  Personally, the most
> > important reason here for me is not having to pollute the current
> > closure with a variable. And this could actually be solved another
> > way, by allowing the use of `var` in a capture list, which would let
> > you say something like `AnyGenerator({ [var state=foo] in ... })`.
> > Given all this, at this point I'm actually leaning towards
> > saying`sequence (state:next:)` doesn't pull its own weight and we
> > should just go with `sequence (initial:next:)`.  -Kevin Ballard
> 
> We forgot to mention this earlier: we prefer “first” over “initial” as the
> label on the latter.

I agree. I almost suggested this a few days ago, but I didn't want to end up bikeshedding the parameter names. I'm inclined to say that the Swift core team should decide whether to change it to "first" instead of debating it, and if so, make that modification when accepting (assuming of course that it does get accepted).

> The design of AnySequence and AnyIterator dates from a time when the
> compiler was very immature and many design avenues we might have taken
> were not available.  I find the `sequence` forms to be superior in
> general, and IMO at some point we should re-evaluate the interfaces to
> AnySequence and AnyIterator.

That sounds like a reasonable justification for keeping sequence(state:next:).

-Kevin Ballard

> Cheers,
> Dave
> 
> > On Thu, May 19, 2016, at 05:37 PM, Trent Nadeau via swift-evolution wrote:
> >
> >     Ah, yes. I apologize. The fact that state is inout, and the same instance is
> >     always passed in confused me. Thanks for the correction.
> >
> >     On Thu, May 19, 2016 at 7:46 PM, Brent Royal-Gordon
> >     <brent-iffxGAVYld63nE1h+Mp7gA at public.gmane.org> wrote:
> >
> >         > Also note that there's a typo in the second example:
> >         >
> >         > for view in sequence(initial: someView, next: { $0.
> >         > superview }) {
> >         >
> >         > // someView, someView.superview, someView.superview.superview, ...
> >         >
> >         > }
> >         >
> >         >
> >         > should be:
> >         >
> >         > for view in sequence(state: someView, next: { $0.
> >         > superview }) {
> >         >
> >         > // someView, someView.superview, someView.superview.superview, ...
> >         >
> >         > }
> >
> >         I don't think these are mistakes—in each iteration of the loop, $0 is
> >         supposed to be the view from the previous iteration.
> >
> >         If you wanted an example using `state`, here's one which is roughly
> >         equivalent to `stride(from: 1.0, to: 2.0, by: 0.1)`, using a
> >         non-error-accumulating algorithm:
> >
> >         let start = 1.0
> >
> >         let end = 2.0
> >
> >         let distance = 0.1
> >
> >         for color in sequence(state: -1.0, next: { $0 += 1; let next = start +
> >         $0 * distance; return next < end ? next : nil }) {
> >
> >         …
> >
> >         }
> >
> >         --
> >         Brent Royal-Gordon
> >         Architechies
> >
> >     -- 
> >
> >     Trent Nadeau
> >
> >     _______________________________________________
> >
> >     swift-evolution mailing list
> >
> >     swift-evolution-m3FHrko0VLzYtjvyW6yDsg at public.gmane.org
> >
> >     https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> -- 
> Dave
> 


More information about the swift-evolution mailing list