<div dir="ltr">On Tue, Oct 4, 2016 at 7:16 PM, Kevin Ballard <span dir="ltr"><<a href="mailto:kevin@sb.org" target="_blank">kevin@sb.org</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u></u>
<div><div><div class="h5"><div>On Tue, Oct 4, 2016, at 12:01 PM, Xiaodi Wu wrote:<br></div>
<blockquote type="cite"><div dir="ltr"><div><div><div>On Tue, Oct 4, 2016 at 1:49 PM, Kevin Ballard <span dir="ltr"><<a href="mailto:kevin@sb.org" target="_blank">kevin@sb.org</a>></span> wrote:<br></div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><u></u><br></div>
<div><div><div><div>On Tue, Oct 4, 2016, at 11:34 AM, Xiaodi Wu wrote:<br></div>
<blockquote type="cite"><div dir="ltr"><div><div><div>On Tue, Oct 4, 2016 at 1:06 PM, Kevin Ballard via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br></div>
<blockquote style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div><u></u><br></div>
<div><div><span></span><br></div>
<div><span>On Tue, Oct 4, 2016, at 10:44 AM, Mark Lacey wrote:</span><br></div>
<blockquote type="cite"><div><span></span><br></div>
<div><blockquote type="cite"><div><span>On Oct 4, 2016, at 10:29 AM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</span><br></div>
<div><span></span><br></div>
<div><div><div><span>On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:</span><br></div>
<blockquote type="cite"><div><blockquote type="cite"><div><span>On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</span><br></div>
<div><span></span><br></div>
<div><div><div><span>On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:</span><br></div>
<blockquote type="cite"><div><blockquote type="cite"><div><span></span><br></div>
</blockquote></div>
</blockquote></div>
</div>
</blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>...</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><div><div><blockquote type="cite"><div><span>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.</span><br></div>
</blockquote><div><span></span><br></div>
<div><span>But you can't write that, unless you're dealing specifically with an Optional<String>. If you try you'll get an error:</span><br></div>
<div><span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif">unnamed.swift:2:19: error: binary operator '??' cannot be applied to operands of type 'Int?' and 'String'</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"> print("x: \(x ?? "nil")")</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"> ~ ^ ~~~~~</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif">unnamed.swift:2:19: note: overloads for '??' exist with these partially matching parameter lists: (T?, @autoclosure () throws -> T), (T?, @autoclosure () thro</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif">ws -> T?)</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"> print("x: \(x ?? "nil")")</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"> ^</span><span class="m_-4529373775606982413font" style="font-family:menlo,consolas,monospace,sans-serif"></span></span><br></div>
<div><span>This leads to writing code like "… \(x.map(String.init(describing<wbr>:)) ?? "nil")" which is pretty gross.</span><br></div>
</div>
</div>
</blockquote><div><span></span><br></div>
</div>
<div><span>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 <span class="m_-4529373775606982413font" style="font-family:menlo">??</span> operator with a <span class="m_-4529373775606982413font" style="font-family:menlo">(T?, String) -> _StringInterpolationSomething</span> signature that works only in a string interpolation context.</span><br></div>
<div><span></span><br></div>
<div><span>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.</span><br></div>
<div><span></span><br></div>
<div><span>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.</span><br></div>
</blockquote></div>
</div>
</blockquote><div><span></span><br></div>
<div><span>That’s definitely more complex, and seems like a completely orthogonal feature request.</span><br></div>
<div><span></span><br></div>
<blockquote type="cite"><div><div><blockquote type="cite"><span></span><br></blockquote><div><span>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”`.</span><br></div>
</div>
</div>
</blockquote><div><span></span><br></div>
<div><span>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?</span><br></div>
</div>
</blockquote><div><span></span><br></div>
<div><span></span><br></div>
<div>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 <i>does</i> 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(…)".<br></div>
</div>
</blockquote><div><br></div>
<div>I'm confused. Why not just add this to your project?<br></div>
<div><br></div>
<div>```<br></div>
<div><div>extension Optional : CustomStringConvertible {<br></div>
<div> public var description: String {<br></div>
<div> guard let some = self else { return "nil" }<br></div>
<div> return String(describing: some)<br></div>
<div> }<br></div>
<div>}<br></div>
</div>
<div>```<br></div>
</div>
</div>
</div>
</blockquote><div><br></div>
</div>
</div>
<div>Because that's globally changing the behavior of Optional in a way that's very surprising.<br></div>
</div>
</blockquote><div><br></div>
<div>Agreed, but I thought that's what you were asking for above?<br></div>
</div>
</div>
</div>
</blockquote><div><br></div>
</div></div><div>I wanted to change the behavior of string interpolation specifically, not the behavior of `String(describing: someOptionalValue)`.</div></div></blockquote><div><br></div><div>It hadn't occurred to me that this was on the table. It would be very surprising for string interpolation to behave differently from `String.init(describing:)`, would it not?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><span class="HOEnZb"><font color="#888888">
<div>-Kevin</div>
<div><br></div>
</font></span></div>
</blockquote></div><br></div></div>