[swift-evolution] Passing an optional first argument to sequence(first:next:)

Xiaodi Wu xiaodi.wu at gmail.com
Tue Aug 16 20:48:31 CDT 2016


On Tue, Aug 16, 2016 at 7:44 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> On Tue, Aug 16, 2016 at 7:34 PM, Braeden Profile via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Okay, I’m actually confused about the current state of things.
>>
>> Earlier, this was introduced:
>>
>> // This function is silly,
>> // but useful functions may take a similar form
>> func foo(x: Int?) -> Int? {
>>   guard let x = x else { return 0 }
>>   return x > 12 ? nil : x + 1
>> }
>>
>> let a: Int? = nil
>> for i in sequence(first: a, next: { foo($0) })
>> {
>>   // This is a pretty useless thing to do,
>>   // but there are useful things that can be done
>>   // without checking whether `i == nil`
>>   print(i)
>> }
>>
>> …and it returns 14 lines of output.  But this doesn’t make sense.  I
>> expected the anonymous closure for next in sequence(first: Int?, next:
>> (Int?) -> Int??) to raise (foo($0)) to (Optional(foo($0))) to avoid having
>> the type signature end up being (Int?) -> Int?.  In that case, the result
>> of (foo($0)) would always be encapsulated in Optional.Some(), so at the
>> 15th run, it would return (Optional.Some(nil)).  Yet it stops when foo
>> returns nil.  Why is this?
>>
>
> Yeah, I think that's a bug :) Which means it should be fixed whether we
> change the function signature or not.
>

I take that back. Not a bug. `next` would have type `@escaping (Int?) ->
Int??`.

When the result of `foo($0)` is `nil` (i.e. `Optional<Int>.none`) and
that's used as the return value for `next`, it gets promoted to
`Optional<Optional<Int>>.none`, not to `Optional<Optional<Int>>.some(nil)`.
It makes sense, despite looking like gibberish.


>
>> And if you replace "next: { foo($0) }" with "next: foo", then it compiles
>> with the same result.  Replacing it with “next: { Optional(foo($0)) }”
>> gives the result I originally expected.
>>
>> This actually would have made more sense to me if the signature was “func
>> sequence<T>(first: T?, next: (T) -> T?) -> UnfoldFirstSequence<T>”, and
>> “let a = nil" would have caused an empty sequence.  I understand that this
>> is a situation that would change unexpectedly if this stdlib change
>> occurred, but I sure think the changed sequence(first:next:) function makes
>> for a more understandable result.
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160816/fa864ff0/attachment.html>


More information about the swift-evolution mailing list