[swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

Kevin Ballard kevin at sb.org
Tue Oct 4 19:16:36 CDT 2016


On Tue, Oct 4, 2016, at 12:01 PM, Xiaodi Wu wrote:
> On Tue, Oct 4, 2016 at 1:49 PM, Kevin Ballard <kevin at sb.org> wrote:
>> __
>> On Tue, Oct 4, 2016, at 11:34 AM, Xiaodi Wu wrote:
>>> On Tue, Oct 4, 2016 at 1:06 PM, Kevin Ballard via swift-evolution
>>> <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> 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> 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(…)".
>>>
>>> I'm confused. Why not just add this to your project?
>>>
>>> ```
>>> extension Optional : CustomStringConvertible {
>>>     public var description: String {
>>>         guard let some = self else { return "nil" }
>>>         return String(describing: some)
>>>     }
>>> }
>>> ```
>>
>> Because that's globally changing the behavior of Optional in a way
>> that's very surprising.
>
> Agreed, but I thought that's what you were asking for above?

I wanted to change the behavior of string interpolation specifically,
not the behavior of `String(describing: someOptionalValue)`.

-Kevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161004/9cad2415/attachment.html>


More information about the swift-evolution mailing list