<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Oct 4, 2016, at 11:47 AM, Joe Groff via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Oct 4, 2016, at 11:06 AM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div class="">On Tue, Oct 4, 2016, at 10:44 AM, Mark Lacey wrote:<br class=""></div><blockquote type="cite" class=""><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Oct 4, 2016, at 10:29 AM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""></div><div class=""><br class=""></div><div class=""><div class=""><div class="">On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:<br class=""></div><blockquote type="cite" class=""><div class=""><blockquote type="cite" class=""><div class="">On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""></div><div class=""><br class=""></div><div class=""><div class=""><div class="">On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:<br class=""></div><blockquote type="cite" class=""><div class=""><blockquote type="cite" class=""><div class=""><br class=""></div></blockquote></div></blockquote></div></div></blockquote><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">...<br class=""></blockquote></blockquote></blockquote><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><br class=""></blockquote></blockquote></blockquote><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">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.<br class=""></div></blockquote><div class=""><br class=""></div><div class="">But you can't write that, unless you're dealing specifically with an Optional<String>. If you try you'll get an error:<br class=""></div><div class=""><br class=""></div><div class=""><span class="font" 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="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"> print("x: \(x ?? "nil")")</span><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"> ~ ^ ~~~~~</span><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" 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="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;">ws -> T?)</span><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"> print("x: \(x ?? "nil")")</span><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class=""><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"> ^</span><span class="font" style="font-family: menlo, consolas, monospace, sans-serif;"></span><br class=""></div><div class="">This leads to writing code like "… \(x.map(String.init(describing:)) ?? "nil")" which is pretty gross.<br class=""></div></div></div></blockquote><div class=""><br class=""></div></div><div class="">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="Apple-converted-space"> </span><span class="font" style="font-family: Menlo;">??</span><span class="Apple-converted-space"> </span>operator with a<span class="Apple-converted-space"> </span><span class="font" style="font-family: Menlo;">(T?, String) -> _StringInterpolationSomething</span><span class="Apple-converted-space"> </span>signature that works only in a string interpolation context.<br class=""></div><div class=""><br class=""></div><div class="">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.<br class=""></div><div class=""><br class=""></div><div class="">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.<br class=""></div></blockquote></div></div></blockquote><div class=""><br class=""></div><div class="">That’s definitely more complex, and seems like a completely orthogonal feature request.<br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class=""><br class=""></blockquote><div class="">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”`.<br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">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?<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">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 class="">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 class=""></div></div></div></blockquote><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">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.</div></div></blockquote><div><br class=""></div></div>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.<div class=""><br class=""></div><div class="">John.</div></body></html>