[swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments
John McCall
rjmccall at apple.com
Tue Oct 4 17:36:41 CDT 2016
> On Oct 4, 2016, at 11:47 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>> On Oct 4, 2016, at 11:06 AM, Kevin Ballard via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>> On Tue, Oct 4, 2016, at 10:44 AM, Mark Lacey wrote:
>>>
>>>> On Oct 4, 2016, at 10:29 AM, Kevin Ballard via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>
>>>> On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:
>>>>>> On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>>>
>>>>>> On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:
>>>>>>>>
>>>>>>>> ...
>>>>>>>>
>>>>>>> We had this at one point, but we took it out because people would forget to test the nil case. I think `?? ""` or `?? nil` really is the best answer here.
>>>>>>
>>>>>> But you can't write that, unless you're dealing specifically with an Optional<String>. If you try you'll get an error:
>>>>>>
>>>>>> unnamed.swift:2:19: error: binary operator '??' cannot be applied to operands of type 'Int?' and 'String'
>>>>>> print("x: \(x ?? "nil")")
>>>>>> ~ ^ ~~~~~
>>>>>> unnamed.swift:2:19: note: overloads for '??' exist with these partially matching parameter lists: (T?, @autoclosure () throws -> T), (T?, @autoclosure () thro
>>>>>> ws -> T?)
>>>>>> print("x: \(x ?? "nil")")
>>>>>> ^
>>>>>> This leads to writing code like "… \(x.map(String.init(describing:)) ?? "nil")" which is pretty gross.
>>>>>
>>>>> I think that if we're going to add this warning we should make it possible to provide a string as an alternative. It seems like it should be possible to build a ?? operator with a (T?, String) -> _StringInterpolationSomething signature that works only in a string interpolation context.
>>>>>
>>>>> There are some types that aren't trivially constructible, or don't have clear alternatives for the nil case. Other times it might just not make sense to build a new instance simply to turn it into a string. If we're going to make people provide an alternative for optionals in this otherwise simple-to-use construct, let's make it simple to do so.
>>>>>
>>>>> This is undoubtedly a more complex approach that could be considered separately, but I think it would be a valuable part of how developers could transition their code.
>>>
>>> That’s definitely more complex, and seems like a completely orthogonal feature request.
>>>
>>>>>
>>>> I like this idea. This combined with the warning for naively interpolating an Optional would be a good solution, because now when I see the warning I can trivially solve it with `?? "nil”`.
>>>
>>> If you can suppress the warning with `as T?` (where T? is the type of the thing being warned on), you wouldn’t need a form that specifically printed “nil”, correct?
>>
>> How many times do I need to repeat myself? I'm looking for a solution to the problem where printing Optionals sanely (e.g. no "Optional(…)" wrapper for .some values) is a PITA right now. Getting rid of the warning does not solve this problem. This is why I like Nate Cook's idea to enable `?? "nil"` in string interpolations, because it does solve my problem. And with this tool, now the warning on printing Optionals becomes useful because it tells me where to add `?? "nil"`. Getting rid of the warning without the ability to add `?? "nil"` is not helpful to me, because I don't want to print "Optional(…)".
>
> A string interpolation segment can accept any type, so 'x ?? "nil"' arguably ought to be able to work by joining both sides of the ?? to 'Any', as if you'd written `(x as Any?) ?? ("nil" as Any)`. IIRC we have some artificial limitations on deducing `Any`, since it can obviously be problematic to have things like array literals automatically fall into [Any] because you accidentally mixed types, but string interpolations are loosely-typed by design. I wonder if there's anything we could do to admit it in this case.
We generally don't consider existential types as a meet of two non-existential types because (1) finding the most-precise common existential type involves enumerating all the known conformances of each type, which is problematic for a number of reasons, and (2) it can be done for two completely arbitrary types because of Any, but we don't want things like (flag ? "foo" : 123) to type-check without some sort of type annotation.
John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161004/16f1346a/attachment.html>
More information about the swift-evolution
mailing list