On behalf of Dmitri Gribenko, Max Moiseev, and myself:
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.
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.
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.
Cheers,
Dave
···
on Thu May 19 2016, Kevin Ballard <swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:
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@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@public.gmane.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
--
Dave