<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jan 9, 2018, at 10:02 PM, Chris Lattner <<a href="mailto:clattner@nondot.org" class="">clattner@nondot.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<div class=""><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Good afternoon,</div></div></blockquote><div class=""><br class=""></div><div class="">Hi Connor,</div><div class=""><br class=""></div><div class="">Huge +1 for this proposal, I’m thrilled you’re cleaning this up. Couple of detail questions:</div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; background-color: rgb(255, 255, 255);" class=""><a href="https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#proposed-solution" aria-hidden="true" class="anchor" id="user-content-proposed-solution" style="box-sizing: border-box; background-color: transparent; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a></h2><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; background-color: rgb(255, 255, 255);" class="">Detailed design</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; background-color: rgb(255, 255, 255);" class="">To provide a more flexible API, we propose deprecating and ultimately removing the <code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">PlaygroundQuickLook</code> enum and <code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">CustomPlaygroundQuickLookable</code> protocol in favor of a simpler design. Instead, we propose introducing a protocol which just provides the ability to return an <code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Any</code> (or <code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">nil</code>) that serves as a stand-in for the instance being logged:</p></div></div></blockquote><div class=""><br class=""></div><div class="">What is the use-case for a type conforming to this protocol but returning nil? If there is a use case for that, why not have such an implementation return “self” instead?</div></div></div></div></blockquote><div><br class=""></div><div>Riley and Saagar answered this down-thread, but to confirm — returning nil would allow some instances of a type to use the “default” playground logging presentation while others use an alternate presentation instead.</div><div><br class=""></div><div>This isn’t handled by `return self` because, unless I’m mistaken, there’s no way to detect that from the caller’s side (e.g. with two `Any` values, I can’t do `self === self.playgroundRepresentation`). This would be necessary because the intention is that `CustomPlaygroundRepresentable` conformances can chain — if I return an object/value which itself conforms to `CustomPlaygroundRepresentable`, then the playground logger should follow that so that I’m presented the same way as whatever I return would have been. (That’s probably not absolutely true, as the PlaygroundLogger library will likely have some sort of failsafe to prevent infinite chaining here. But I wouldn’t want to rely on such a failsafe mechanism in the design of this API.)</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="">In short, can we change playgroundRepresentation to return Any instead of Any?. Among other things, doing so could ease the case of playground formatting Optional itself, which should presumably get a conditional conformance to this. :-)</div></div></div></div></blockquote><div><br class=""></div><div>I don’t think we can change this to return `Any` instead of `Any?`. I think there are potentially cases where a developer might want to selectively opt-in to this behavior.</div><div><br class=""></div><div>I also don’t think that `Optional` would get a conditional conformance to this. I’m not proposing that any standard library or corelibs types gain conformances to this protocol. Instead, it’s up to a playground logger (such as PlaygroundLogger in <a href="https://github.com/apple/swift-xcode-playground-support" class="">swift-xcode-playground-support</a>) to recognize these types and handle them accordingly. The playground logger would look through the `Optional` so that this would effectively be true, but ideally the log data generated by a logger would indicate that it was wrapped by `Optional.some`.</div><div><br class=""></div><div><div class="">One possibility would be to change the API so that it returns an enum. Imagine:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>enum PlaygroundLoggingBehavior {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// Asks the playground logger to generate the standard logging for `self`.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>case standard</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// Asks the playground logger to generate logging for the given `Any` instead of `self`.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>case custom(Any)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol CustomPlaygroundLoggable {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// Returns the `PlaygroundLoggingBehavior` to use for `self`.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>var playgroundLoggingBehavior: PlaygroundLoggingBehavior { get }</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class="">(To Saagar’s point in another email — you could even add a `case none` to PlaygroundLoggingBehavior to inhibit logging of a particular instance.)</div><div class=""><br class=""></div><div class="">`CustomPlaygroundLoggable` would be a little clunkier to implement than `CustomPlaygroundRepresentable` is, as in the common case folks would have to write `return .custom(…)`. It’s possible that the clarity and additional flexibility this grants outweighs that cost; I’m not sure, and would love feedback on that.</div></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; background-color: rgb(255, 255, 255);"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;" class=""><span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> Implementors of `CustomPlaygroundRepresentable` may return a value of one of</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> the above types to also receive a specialized log representation.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> Implementors may also return any other type, and playground logging will</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> generated structured logging for the returned value.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">protocol</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">CustomPlaygroundRepresentable</span> {
</pre></div></div></div></blockquote><div class="">On the naming bikeshed, the closest analog to this feature is CustomStringConvertible, which is used when a type wants to customize the default conversion to string. As such, have you considered CustomPlaygroundConvertible for consistency with it?</div><div class=""><br class=""></div><div class="">The only prior art for the word “Representable” in the standard library is RawRepresentable, which is quite a different concept.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; background-color: rgb(255, 255, 255);"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;" class=""> <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> Returns the custom playground representation for this instance, or nil if</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> the default representation should be used.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);">///</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> If this type has value semantics, the instance returned should be</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">///</span> unaffected by subsequent mutations if possible.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">var</span> playgroundRepresentation<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">Any</span><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">?</span> { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">get</span> }
</pre></div></div></div></blockquote><div class="">Again to align with CustomStringConvertible which has a ‘description’ member, it might make sense to name this member “playgroundDescription”.</div></div></div></div></blockquote><div><br class=""></div><div>I’m definitely open to different names for this. (`CustomPlaygroundRepresentable` was inspired by the API I’m removing, `CustomPlaygroundQuickLookable`, as they both take their sole property and make them -able.)</div><div><br class=""></div><div>I do like the `playgroundDescription` name for the property, but am a little hesitant to use the name `CustomPlaygroundConvertible` because conforming types can’t be converted to playgrounds. I can’t come up with an appropriate word in `CustomPlaygroundThingConvertible` to use in place of `Thing`, though. (If we end up pivoting to the enum I described above then something like `CustomPlaygroundLoggable` would be more appropriate.)</div><div><br class=""></div><div>Connor</div></div></body></html>