<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">+ Erica, Kevin, as the authors of the original proposal.<div class=""><br class=""></div><div class="">Do you remember the problem of non-emptiness being discussed before? And if not, what’s your opinion on the proposed change?</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Max<br class=""><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 19, 2016, at 7:53 AM, Tim Vermeulen <<a href="mailto:tvermeulen@me.com" class="">tvermeulen@me.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi Max, thanks for having a look.</div><div class=""><br class=""></div><div class="">A big part of why I’m not really happy with the current implementation is that the function always produces a nonempty sequence, though the compiler doesn’t know it. `sequence(first: first, next: next).last` returns an optional, even though it can’t possibly be nil. The same goes for something like `sequence(first: 5, next: { $0 * 3 }).first(where: { $0 > 1000 })`, because the sequence is infinite, which means `first(while:)` will either keep running forever, or return a non-optional.</div><div class=""><br class=""></div><div class="">Ideally, we’d have three types of sequences, with three corresponding `sequence(first:next:)` functions:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">func sequence<T>(first: T?, next: (T) -> T?)</font><font face="Menlo" class=""> — </font>returns any sequence<br class=""><span style="font-family: Menlo;" class="">func sequence<T>(first: T, next: (T) -> T?)</span><font face="Menlo" class=""> — </font>returns a nonempty sequence</div><div class=""><span style="font-family: Menlo;" class="">func sequence<T>(first: T, next: (T) -> T) </span><font face="Menlo" class=""> — </font>returns an infinite sequence</div><div class=""><br class=""></div><div class="">Default implementations for methods on sequences would either return optionals or non-optionals depending on their emptiness/finiteness. We just have the first kind of sequence right now, so in that regard it would make sense to also give `sequence(first:next)` the corresponding signature. Later, when the language / standard library supports the other two kinds of sequences (if that ever happens), the other versions could be added.</div><div class=""><br class=""></div><div class="">Another reason that makes me think that the version that accepts an optional `first` argument is more natural, is the fact that the function body doesn’t need to be changed at all. It supports optional seeds by design; only the signature prevents it.</div><div class=""><br class=""></div><div class="">I know these arguments might not be very convincing, but I feel like Swift misses an opportunity if it unnecessarily constrains the `first` parameter to be non-optional. The `.lazy.flatMap({ $0 })` alternative that you pointed out does work, but it makes everything very unreadable: not just the `.lazy.flatMap({ $0 })` part, but also the body of the `next` parameter because you’re now dealing with optionals (i.e. you have to `flatMap` over the closure argument). The best solution I’ve come up with is to copy the `sequence(first:next)` implementation from the source code and change the signature. :-/</div><div class=""><br class=""></div><div class="">`sequence(state:next:)` isn’t very appropriate for this task either, because naive usage with an optional seed has the downside of being unnecessarily eager just like a naive `sequence(first:next)` implementation (as described in a comment in the source code).</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 19 Aug 2016, at 00:18, Max Moiseev <<a href="mailto:moiseev@apple.com" class="">moiseev@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi Tim,</div><div class=""><br class=""></div><div class="">Thanks for bringing this up.</div><div class="">Here are my thoughts on the change you’re proposing.</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span style="font-size: 12px;" class="">func sequence<T>(first: T, next: (T) -> T?) -> UnfoldFirstSequence<T></span></font></div><div class=""><br class=""></div><div class="">To me the type of the function as it is tells a clear story of what’s going to happen: take the `first`, make it a head of the resulting sequence, and then try to produce the tail by a series of applications of `next`. The only thing that controls when the sequence generation terminates is the result of `next`.</div><div class=""><br class=""></div><div class="">If we change the type of `first` to an Optional<T>, it would make the termination condition non-trivial. After all, the only thing it would do is try to unwrap the `first`, before doing what it needs to, but we already have a `map` for that. One should be able to simply do the `first.map { sequence(first: $0, next: next) } ?? []` but that won’t work with the types very well, unfortunately.</div><div class=""><br class=""></div><div class="">As an alternative, `let first: Int? = ...; sequence(first: first, next: next).flatMap({$0})` (or even `.lazy.flatMap({$0})`) will do the right thing without making an API more complex.</div><div class=""><br class=""></div><div class="">I see the point of `sequence(first:next:)` to be precisely the "generate the non-empty sequence using a seed and a simple producer", for anything more than that, there is `sequence(state:next:)`.</div><div class=""><br class=""></div><div class="">What do you think?</div><div class=""><br class=""></div><div class="">Max</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Aug 14, 2016, at 4:27 PM, Tim Vermeulen via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">sequence(first:next:) takes a non-optional first argument. Is there a reason for that? sequence(state:next:) allows empty sequences, and I don’t see why sequence(first:next:) shouldn’t. The fix would be to simply add the `?` in the function signature; no other changes are required to make it work.<br class=""><br class="">I considered just filing a bug report, but since this is a change of the public API...<br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></body></html>