<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 4, 2015, at 10:26 PM, Dmitri Gribenko &lt;<a href="mailto:gribozavr@gmail.com" class="">gribozavr@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">On Fri, Dec 4, 2015 at 10:21 PM, Andrew Trick &lt;</span><a href="mailto:atrick@apple.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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="">atrick@apple.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">&gt; wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><br class=""><blockquote type="cite" class="">On Dec 4, 2015, at 10:05 PM, Dmitri Gribenko &lt;<a href="mailto:gribozavr@gmail.com" class="">gribozavr@gmail.com</a>&gt; wrote:<br class=""><br class="">On Fri, Dec 4, 2015 at 10:00 PM, Andrew Trick &lt;<a href="mailto:atrick@apple.com" class="">atrick@apple.com</a>&gt; wrote:<br class=""><blockquote type="cite" class="">I’m adding runtime functionality to support optional casts and ran into some Optional to String conversion behavior that is currently somewhat accidental—it will break when I add functionality. I want to understand the desired behavior before doing extra work to fix it.<br class=""><br class="">Currently swift does this:<br class=""><br class=""><blockquote type="cite" class="">print(Int?(3))<br class=""></blockquote>Optional(3)<br class=""><blockquote type="cite" class="">print(String?("meow"))<br class=""></blockquote>Optional("meow")<br class=""><br class="">I think swift should do this:<br class=""><br class=""><blockquote type="cite" class="">print(Int?(3))<br class=""></blockquote>3<br class=""><blockquote type="cite" class="">print(String?("meow"))<br class=""></blockquote>"meow"<br class=""><blockquote type="cite" class="">debugPrint(Int?(3))<br class=""></blockquote>Optional(3)<br class=""><blockquote type="cite" class="">debugPrint(String?("meow"))<br class=""></blockquote>Optional("meow")<br class=""><br class="">When a value already knows how to represent itself as a string, I don't think that the string "Optional" belongs in the textual representation.<br class=""><br class="">When debugging data structures, it makes sense to include the "Optional" indicator.<br class=""><br class="">What was the intention here and what do people think is the desired behavior?<br class=""></blockquote><br class="">This behavior was not accidental. &nbsp;Here's the rationale:<br class=""><br class="">If an Optional is nil, it should somehow indicate that. &nbsp;Whatever the<br class="">representation is, it would be engineer-oriented and not suitable for<br class="">end users. &nbsp;Thus, Optional should never be printed to users, it would<br class="">only ever be presented to engineers, and thus its print() and<br class="">debugPrint() representations should be the same.<br class=""><br class="">Dmitri<br class=""></blockquote><br class="">I think you're saying that it's the programmer's responsibility not to construct a user-visible String from an Optional.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">No, the responsibility is not to display it to users. &nbsp;It is OK to e.g., log it.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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="">By accidental, I mean that Optional does not conform to CustomStringConvertible. If we want "Optional" to be part of the string conversion, then this conformance needs to exist, or I need to add some special handling of Optional. Do you see any problem with me adding that conformance?<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">Yes, the same behavior should also apply to any user-defined type: if</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">there is only CustomDebugStringConvertible conformance, it should be</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">used for String(x) initialization.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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="">Incidentally, when *do* we want debug string conversion to deviate? Or is it just a customization point we anticipate to be useful?<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">For example, in String: the user-presentable representation is the</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">string itself, the engineer-oriented representation shows all special</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">characters as escape sequences.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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; float: none; display: inline !important;" class="">Dmitri</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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=""></div></blockquote></div><br class=""><div class=""><div class="">I understand, thanks for the explanation. But Optionals are not like</div><div class="">other user-defined types in this respect. Let me clarify with an</div><div class="">example...</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">class A : CustomStringConvertible, CustomDebugStringConvertible {&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; init() {}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; var description: String { get { return "Apple" } }&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; var debugDescription: String { get { return "Swift" } }&nbsp;</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">print(A?(A()) is CustomStringConvertible)</font></div><div class=""><font face="Menlo" class="">// true</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// Now, Optional does not conform to CustomStringConvertible, but as</font></div><div class=""><font face="Menlo" class="">// you can see above it is convertible to CustomStringConvertible.</font></div><div class=""><font face="Menlo" class="">// As print_unlocked is currently written, the behavior should be:</font></div><div class=""><font face="Menlo" class="">print(String(A?(A())))</font></div><div class=""><font face="Menlo" class="">Apple</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// But as you explained, that is not the behavior we want. We could fix</font></div><div class=""><font face="Menlo" class="">// it by making Optional counter-intuitively conform to</font></div><div class=""><font face="Menlo" class="">// CustomStringConvertible. This prevents down conversion to the wrapped</font></div><div class=""><font face="Menlo" class="">// type, instead printing "Optional" and the payload's debug string.</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">extension Optional : CustomStringConvertible {</font></div><div class=""><font face="Menlo" class="">&nbsp; /// A textual representation of `self`, suitable for debugging.</font></div><div class=""><font face="Menlo" class="">&nbsp; ///</font></div><div class=""><font face="Menlo" class="">&nbsp; /// Optional has no representation suitable for an output</font></div><div class=""><font face="Menlo" class="">&nbsp; /// stream. Consequently, String conversion should always produce a</font></div><div class=""><font face="Menlo" class="">&nbsp; /// debug string indicating the Optional type and including the</font></div><div class=""><font face="Menlo" class="">&nbsp; /// debug representation of the wrapped type.</font></div><div class=""><font face="Menlo" class="">&nbsp; ///</font></div><div class=""><font face="Menlo" class="">&nbsp; /// Optional must conform to CustomStringConvertible to avoid</font></div><div class=""><font face="Menlo" class="">&nbsp; /// automatic conversion to its wrapped type during String</font></div><div class=""><font face="Menlo" class="">&nbsp; /// conversion.</font></div><div class=""><font face="Menlo" class="">&nbsp; public var description: String {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return debugDescription</font></div><div class=""><font face="Menlo" class="">&nbsp; }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class="">print(String(A?(A())))</font></div><div class=""><font face="Menlo" class="">Optional(Swift)</font></div></div><div class=""><br class=""></div><div class="">I think this is the way to go.</div><div class=""><br class=""></div><div class="">Andy</div></body></html>