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

Xiaodi Wu xiaodi.wu at gmail.com
Mon Aug 15 19:41:37 CDT 2016


On Mon, Aug 15, 2016 at 7:23 PM, Tim Vermeulen <tvermeulen at me.com> wrote:

>
> On 16 Aug 2016, at 02:11, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Mon, Aug 15, 2016 at 7:03 PM, Tim Vermeulen <tvermeulen at me.com> wrote:
>
>> If I'm not mistaken, the type of T can be inferred from the `next`
>> closure here. $0 is an optional, so you end up with a sequence of optionals.
>>
>
> Currently, yes. But if we have both
>
> public func sequence<T>(first: T, next: @escaping (T) -> T?) ->
> UnfoldFirstSequence<T> { ... }
> public func sequence<T>(first: T?, next: @escaping (T) -> T?) ->
> UnfoldFirstSequence<T> { ... }
>
> then $0 could be inferred to be of type `T` or `T?`, right?
>
>
> I was indeed talking about replacing the first function by the second, not
> having them side by side.
>
>
> And if we replace the first function with the second (instead of having
> both), then the same code that gives you an UnfoldFirstSequence<T?> today
> would give you an UnfoldFirstSequence<T> tomorrow, which would be the most
> pernicious way to break code (subtle, hard to catch unless you know what
> you're looking for, with a potentially massive difference in behavior).
>
>
> I’m not sure I follow. First of all, I think an unfold sequence with an
> optional element is pretty far-fetched, but fair enough, they may exist.
> But why would the type suddenly change? Type inference would still figure
> out the right type, no? An example would be greatly appreciated, because I
> don’t see how this could form a problem.
>


```
// 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)
}
```

If you change the function signature, the number of lines printed by this
example code will change from 14 to 0.


On 16 Aug 2016, at 00:51, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> Given:
>>
>> let foo: T? = something()
>> let bar = sequence(first: foo, next: { $0?.frobnicate() })
>>
>> If first could be of type `T` or `T?`, is bar of type `UnfoldSequence<T>`
>> or `UnfoldSequence<T?>`?
>> On Mon, Aug 15, 2016 at 17:15 Tim Vermeulen via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>> I doubt that’s it, in no way is an an empty sequence inherently unsafe.
>>> The entire standard library is built with empty sequences in mind. I’m more
>>> inclined to think it’s an oversight.
>>>
>>> On 15 Aug 2016, at 23:15, Maximilian Hünenberger <m.huenenberger at me.com>
>>> wrote:
>>>
>>> Ok, I see. However this could be a potential source of bugs/performance
>>> issues where you don't consider the nil case and you do some unnecessary
>>> work. By prohibiting to pass nil you have to manually unwrap and you
>>> immediately see the "optionality".
>>>
>>> Am 15.08.2016 um 22:36 schrieb Tim Vermeulen <tvermeulen at me.com>:
>>>
>>> Oh, that’s true, I misunderstood your previous message. It’s not about
>>> passing nil, but it’s about passing optionals. The point is to be able to
>>> do something like this:
>>>
>>> let number = functionThatReturnsAnOptional()
>>> sequence(first: number, next: { $0 % 2 == 0 ? $0 / 2 : nil })
>>>
>>> On 15 Aug 2016, at 22:26, Maximilian Hünenberger <m.huenenberger at me.com>
>>> wrote:
>>>
>>> Probably I didn't understand your proposal. What do you want to change
>>> exactly?
>>>
>>> I thought:
>>> public func sequence<T>(first: T, next: @escaping (T) -> T?) ->
>>> UnfoldFirstSequence<T> { ... }
>>>
>>> To:
>>> public func sequence<T>(first: T?, next: @escaping (T) -> T?) ->
>>> UnfoldFirstSequence<T> { ... }
>>>
>>> Am 15.08.2016 um 22:17 schrieb Tim Vermeulen <tvermeulen at me.com>:
>>>
>>> You can’t; the `first` parameter has type `T`, not `T?`.
>>>
>>> On 15 Aug 2016, at 22:10, Maximilian Hünenberger <m.huenenberger at me.com>
>>> wrote:
>>>
>>> Hi Tim,
>>>
>>> If you pass "nil" to "first" isn't this an empty sequence? So it would
>>> be redundant.
>>>
>>> Best regards
>>> Maximilian
>>>
>>> Am 15.08.2016 um 01:27 schrieb Tim Vermeulen via swift-evolution <
>>> swift-evolution at swift.org>:
>>>
>>> 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.
>>>
>>> I considered just filing a bug report, but since this is a change of the
>>> public API...
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.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
>>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160815/68fdb250/attachment.html>


More information about the swift-evolution mailing list