Yes, it will — if a type does not conform to `CustomPlaygroundRepresentable`, 
PlaygroundLogger will continue to log it structurally.

Connor

> On Jan 9, 2018, at 3:56 PM, Saagar Jha <saa...@saagarjha.com> wrote:
> 
> I’ve just glanced through this, so I apologize if this was already addressed, 
> but will the default behavior (i.e. that of something that doesn’t conform to 
> CustomPlaygroundRepresentable) remain the same?
> 
> Saagar Jha
> 
>> On Jan 9, 2018, at 15:19, Connor Wakamo via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> Good afternoon,
>> 
>> In preparation for ABI stability, I’ve reviewed the API exposed by the 
>> standard library for providing customized “quick looks” in playgrounds. This 
>> is exposed as the PlaygroundQuickLook enum and the 
>> CustomPlaygroundQuickLookable protocol. The PlaygroundQuickLook has a 
>> handful of issues:
>> 
>>      - It hard-codes the list of supported types in the standard library, 
>> meaning that PlaygroundLogger/IDEs cannot gain support for new types without 
>> standard library changes (including swift-evolution review)
>>      - The cases of the enum are poorly typed: there are cases like `.view` 
>> and `.color` which take NS/UIView or NS/UIColor instances, respectively, but 
>> since they’re in the standard library, they have to be typed as taking `Any` 
>> instead
>>      - The names of some of these enum cases do not seem to match Swift 
>> naming conventions)
>> 
>> To that end, I am proposing the following:
>> 
>>      - Deprecate PlaygroundQuickLook and CustomPlaygroundQuickLookable in 
>> Swift 4.1 (including in the Swift 3 compatibility mode)
>>      - Remove PlaygroundQuickLook and CustomPlaygroundQuickLookable in Swift 
>> 5 to avoid including them in the stable ABI (this affects the compatibility 
>> modes, too)
>>      - Introduce a new protocol, CustomPlaygroundRepresentable, in the 
>> PlaygroundSupport library in Swift 4.1:
>> 
>>              protocol CustomPlaygroundRepresentable {
>>                      /// Returns an alternate object or value which should 
>> stand in for the receiver in playground logging, or nil if the receiver’s 
>> default representation is preferred.
>>                      var playgroundRepresentation: Any? { get }
>>              }
>> 
>>      - Update the PlaygroundLogger library in Swift 4.1 to support both 
>> CustomPlaygroundRepresentable and 
>> PlaygroundQuickLook/CustomPlaygroundQuickLookable
>>      - Provide a compatibility shim library which preserves 
>> PlaygroundQuickLook and CustomPlaygroundQuickLookable as deprecated in Swift 
>> 3/4 and unavailable in Swift 5, but only in playgrounds (including in the 
>> auxiliary source files stored inside a playground)
>> 
>> I’ve put a full proposal below. Please let me know what you think of this 
>> proposal; I’d like to get some feedback before taking this through the 
>> review process, but I’ll need to get that quickly so I can get it under 
>> review soon as this is targeted at Swift 4.1.
>> 
>> Thanks,
>> Connor
>> 
>> —
>> 
>> Playground QuickLook API Revamp
>> 
>> Proposal: SE-NNNN 
>> <https://github.com/cwakamo/swift-evolution/blob/playground-quicklook-api-revamp/proposals/NNNN-playground-quicklook-api-revamp.md>
>> Authors: Connor Wakamo <https://github.com/cwakamo>
>> Review Manager: TBD
>> Status: Awaiting implementation
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#introduction>Introduction
>> 
>> The standard library currently includes API which allows a type to customize 
>> its representation in Xcode playgrounds and Swift Playgrounds. This API 
>> takes the form of the PlaygroundQuickLook enum which enumerates types which 
>> are supported for quick looks, and the CustomPlaygroundQuickLookable 
>> protocol which allows a type to return a custom PlaygroundQuickLook value 
>> for an instance.
>> 
>> This is brittle, and to avoid dependency inversions, many of the cases are 
>> typed as taking Any instead of a more appropriate type. This proposal 
>> suggests that we deprecate PlaygroundQuickLook and 
>> CustomPlaygroundQuickLookable in Swift 4.1 so they can be removed entirely 
>> in Swift 5, preventing them from being included in the standard library's 
>> stable ABI. To maintain compatibility with older playgrounds, the deprecated 
>> symbols will be present in a temporary compatibility shim library which will 
>> be automatically imported in playground contexts. (This will represent an 
>> intentional source break for projects, packages, and other non-playground 
>> Swift code which use PlaygroundQuickLook or CustomPlaygroundQuickLookable 
>> when they switch to the Swift 5.0 compiler, even in the compatibility modes.)
>> 
>> Since it is still useful to allow types to provide alternate representations 
>> for playgrounds, we propose to add a new protocol to the PlaygroundSupport 
>> framework which allows types to do just that. (PlaygroundSupport is a 
>> framework delivered by the swift-xcode-playground-support project 
>> <https://github.com/apple/swift-xcode-playground-support> which provides API 
>> specific to working in the playgrounds environment). The new 
>> CustomPlaygroundRepresentable protocol would allow instances to return an 
>> alternate object or value (as an Any) which would serve as their 
>> representation. The PlaygroundLogger framework, also part of 
>> swift-xcode-playground-support, will be updated to understand this protocol.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal 
>> <https://lists.swift.org/pipermail/swift-evolution/>
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#motivation>Motivation
>> 
>> The PlaygroundQuickLook enum which currently exists in the standard library 
>> is substandard:
>> 
>> public enum PlaygroundQuickLook {
>>   case text(String)
>>   case int(Int64)
>>   case uInt(UInt64)
>>   case float(Float32)
>>   case double(Float64)
>>   case image(Any)
>>   case sound(Any)
>>   case color(Any)
>>   case bezierPath(Any)
>>   case attributedString(Any)
>>   case rectangle(Float64, Float64, Float64, Float64)
>>   case point(Float64, Float64)
>>   case size(Float64, Float64)
>>   case bool(Bool)
>>   case range(Int64, Int64)
>>   case view(Any)
>>   case sprite(Any)
>>   case url(String)
>>   case _raw([UInt8], String)
>> }
>> The names of these enum cases do not necessarily match current Swift naming 
>> conventions (e.g. uInt), and many cases are typed as Any to avoid dependency 
>> inversions between the standard library and higher-level frameworks like 
>> Foundation and AppKit or UIKit. It also contains cases which the 
>> PlaygroundLogger framework does not understand (e.g. sound), and this 
>> listing of cases introduces revlock between PlaygroundLogger and the 
>> standard library that makes it challenging to introduce support for new 
>> types of quick looks.
>> 
>> Values of this enum are provided to the PlaygroundLogger framework by types 
>> via conformances to the CustomPlaygroundQuickLookable protocol:
>> 
>> public protocol CustomPlaygroundQuickLookable {
>>   var customPlaygroundQuickLook: PlaygroundQuickLook { get }
>> }
>> This protocol itself is not problematic, but if PlaygroundQuickLook is being 
>> removed, then it needs to be removed as well. Additionally, there is a 
>> companion underscored protocol which should be removed as well:
>> 
>> public protocol _DefaultCustomPlaygroundQuickLookable {
>>   var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook { get }
>> }
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#proposed-solution>Proposed
>>  solution
>> 
>> To solve this issue, we propose the following changes:
>> 
>> Introduce a new CustomPlaygroundRepresentable protocol in PlaygroundSupport 
>> in Swift 4.1 to allow types to provide an alternate representation for 
>> playground logging
>> Deprecate PlaygroundQuickLook and CustomPlaygroundQuickLookable in Swift 
>> 4.1, suggesting users use CustomPlaygroundRepresentable instead
>> Remove PlaygroundQuickLook and CustomPlaygroundQuickLookable from the 
>> standard library in Swift 5.0
>> Provide an automatically-imported shim library for the playgrounds context 
>> to provide the deprecated instances of PlaygroundQuickLook and 
>> CustomPlaygroundQuickLookable for pre-Swift 5 playgrounds
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#detailed-design>Detailed
>>  design
>> 
>> To provide a more flexible API, we propose deprecating and ultimately 
>> removing the PlaygroundQuickLook enum and CustomPlaygroundQuickLookable 
>> protocol in favor of a simpler design. Instead, we propose introducing a 
>> protocol which just provides the ability to return an Any (or nil) that 
>> serves as a stand-in for the instance being logged:
>> 
>> /// A type that supplies a custom representation for playground logging.
>> ///
>> /// All types have a default representation for playgrounds. This protocol
>> /// allows types to provide custom representations which are then logged in
>> /// place of the original instance. Alternatively, implementors may choose to
>> /// return `nil` in instances where the default representation is preferable.
>> ///
>> /// Playground logging can generate, at a minimum, a structured 
>> representation
>> /// of any type. Playground logging is also capable of generating a richer,
>> /// more specialized representation of core types -- for instance, the 
>> contents
>> /// of a `String` are logged, as are the components of an `NSColor` or
>> /// `UIColor`.
>> ///
>> /// The current playground logging implementation logs specialized
>> /// representations of at least the following types:
>> ///
>> /// - `String` and `NSString`
>> /// - `Int` and `UInt` (including the sized variants)
>> /// - `Float` and `Double`
>> /// - `Bool`
>> /// - `Date` and `NSDate`
>> /// - `NSAttributedString`
>> /// - `NSNumber`
>> /// - `NSRange`
>> /// - `URL` and `NSURL`
>> /// - `CGPoint`, `CGSize`, and `CGRect`
>> /// - `NSColor`, `UIColor`, `CGColor`, and `CIColor`
>> /// - `NSImage`, `UIImage`, `CGImage`, and `CIImage`
>> /// - `NSBezierPath` and `UIBezierPath`
>> /// - `NSView` and `UIView`
>> ///
>> /// Playground logging may also be able to support specialized 
>> representations
>> /// of other types.
>> ///
>> /// Implementors of `CustomPlaygroundRepresentable` may return a value of 
>> one of
>> /// the above types to also receive a specialized log representation.
>> /// Implementors may also return any other type, and playground logging will
>> /// generated structured logging for the returned value.
>> public protocol CustomPlaygroundRepresentable {
>>   /// Returns the custom playground representation for this instance, or nil 
>> if
>>   /// the default representation should be used.
>>   ///
>>   /// If this type has value semantics, the instance returned should be
>>   /// unaffected by subsequent mutations if possible.
>>   var playgroundRepresentation: Any? { get }
>> }
>> Additionally, instead of placing this protocol in the standard library, we 
>> propose placing this protocol in the PlaygroundSupport framework, as it is 
>> only of interest in the playgrounds environment. Should demand warrant it, a 
>> future proposal could suggest lowering this protocol into the standard 
>> library.
>> 
>> If this proposal is accepted, then code like the following:
>> 
>> extension MyStruct: CustomPlaygroundQuickLookable {
>>   var customPlaygroundQuickLook: PlaygroundQuickLook {
>>     return .text("A description of this MyStruct instance")
>>   }
>> }
>> would be replaced with something like the following:
>> 
>> extension MyStruct: CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: Any? {
>>     return "A description of this MyStruct instance"
>>   }
>> }
>> This proposal also allows types which wish to be represented structurally 
>> (like an array or dictionary) to return a type which is logged structurally 
>> instead of requiring an implementation of the CustomReflectable protocol:
>> 
>> extension MyStruct: CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: Any? {
>>     return [1, 2, 3]
>>   }
>> }
>> This is an enhancement over the existing CustomPlaygroundQuickLookable 
>> protocol, which only supported returning opaque, quick lookable values for 
>> playground logging. (By returning an Any?, it also allows instances to 
>> opt-in to their standard playground representation if that is preferable 
>> some cases.)
>> 
>> Implementations of CustomPlaygroundRepresentable may potentially chain from 
>> one to another. For instance, with:
>> 
>> extension MyStruct: CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: Any? {
>>     return "MyStruct representation"
>>   }
>> }
>> 
>> extension MyOtherStruct: CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: Any? {
>>     return MyStruct()
>>   }
>> }
>> Playground logging for MyOtherStruct would generate the string "MyStruct 
>> representation" rather than the structural view of MyStruct. It is legal, 
>> however, for playground logging implementations to cap chaining to a 
>> reasonable limit to guard against infinite recursion.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#source-compatibility>Source
>>  compatibility
>> 
>> This proposal is explicitly suggesting that we make a source-breaking change 
>> in Swift 5 to remove PlaygroundQuickLook, CustomPlaygroundQuickLookable, and 
>> _DefaultCustomPlaygroundQuickLookable. Looking at a GitHub search, there are 
>> fewer than 900 references to CustomPlaygroundQuickLookable in Swift source 
>> code; from a cursory glance, many of these are duplicates, from forks of the 
>> Swift repo itself (i.e. the definition of CustomPlaygroundQuickLookable in 
>> the standard library), or are clearly implemented using pre-Swift 3 names of 
>> the enum cases in PlaygroundQuickLook. (As a point of comparison, there are 
>> over 185,000 references to CustomStringConvertible in Swift code on GitHub, 
>> and over 145,000 references to CustomDebugStringConvertible, so 
>> CustomPlaygroundQuickLookable is clearly used many orders of magnitude less 
>> than those protocols.) Furthermore, it does not appear that any projects 
>> currently in the source compatibility suite use these types.
>> 
>> However, to mitigate the impact of this change, we propose to provide a 
>> limited source compatibility shim for the playgrounds context. This will be 
>> delivered as part of the swift-xcode-playground-support project as a library 
>> containing the deprecated PlaygroundQuickLook and 
>> CustomPlaygroundQuickLookable protocols. This library would be imported 
>> automatically in playgrounds. This source compatibility shim would not be 
>> available outside of playgrounds, so any projects, packages, or other Swift 
>> code would be intentionally broken by this change when upgrading to the 
>> Swift 5.0 compiler, even when compiling in a compatibility mode.
>> 
>> Due to the limited usage of these protocols, and the potential challenge in 
>> migration, this proposal does not include any proposed migrator changes to 
>> support the replacement of CustomPlaygroundQuickLookable 
>> withCustomPlaygroundRepresentable. Instead, we intend for Swift 4.1 to be a 
>> deprecation period for these APIs, allowing any code bases which implement 
>> CustomPlaygroundQuickLookable to manually switch to the new protocol. While 
>> this migration may not be trivial programatically, it should -- in most 
>> cases -- be fairly trivial for someone to hand-migrate 
>> toCustomPlaygroundRepresentable. During the deprecation period, the 
>> PlaygroundLogger framework will continue to honor implementations of 
>> CustomPlaygroundQuickLookable, though it will prefer implementations 
>> ofCustomPlaygroundRepresentable if both are present on a given type.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#effect-on-abi-stability>Effect
>>  on ABI stability
>> 
>> This proposal affects ABI stability as it removes an enum and a pair of 
>> protocols from the standard library. Since this proposal proposes adding 
>> CustomPlaygroundRepresentable to PlaygroundSupport instead of the standard 
>> library, there is no impact of ABI stability from the new protocol, as 
>> PlaygroundSupport does not need to maintain a stable ABI, as its clients -- 
>> playgrounds -- are always recompiled from source.
>> 
>> Since playgrounds are always compiled from source, the temporary shim 
>> library does not represent a new ABI guarantee, and it may be removed if the 
>> compiler drops support for the Swift 3 and 4 compatibility modes in a future 
>> Swift release.
>> 
>> Removing PlaygroundQuickLook from the standard library also potentially 
>> allows us to remove a handful of runtime entry points which were included to 
>> support the PlaygroundQuickLook(reflecting:) API.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#effect-on-api-resilience>Effect
>>  on API resilience
>> 
>> This proposal does not impact API resilience.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#alternatives-considered>Alternatives
>>  considered
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#do-nothing>Do
>>  nothing
>> 
>> One valid alternative to this proposal is to do nothing: we could continue 
>> to live with the existing enum and protocol. As noted above, these are 
>> fairly poor, and do not serve the needs of playgrounds particularly well. 
>> Since this is our last chance to remove them prior to ABI stability, we 
>> believe that doing nothing is not an acceptable alternative.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#provide-type-specific-protocols>Provide
>>  type-specific protocols
>> 
>> Another alternative we considered was to provide type-specific protocols for 
>> providing playground representations. We would introduce new protocols like 
>> CustomNSColorConvertible, CustomNSAttributedStringConvertible, etc. which 
>> would allow types to provide representations as each of the 
>> opaquely-loggable types supported by PlaygroundLogger.
>> 
>> This alternative was rejected as it would balloon the API surface for 
>> playgrounds, and it also would not provide a good way to select a preferred 
>> representation. (That is, what would PlaygroundLogger select as the 
>> representation of an instance if it implemented both 
>> CustomNSColorConvertible and CustomNSAttributedStringConvertible?)
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#implement-customplaygroundrepresentable-in-the-standard-library>Implement
>>  CustomPlaygroundRepresentable in the standard library
>> 
>> As an alternative to implementing CustomPlaygroundRepresentable in 
>> PlaygroundSupport, we could implement it in the standard library. This would 
>> make it available in all contexts (i.e. in projects and packages, not just 
>> in playgrounds), but this protocol is not particularly useful outside of the 
>> playground context, so this proposal elects not to 
>> placeCustomPlaygroundRepresentable in the standard library.
>> 
>> Additionally, it should be a source-compatible change to move this protocol 
>> to the standard library in a future Swift version should that be desirable. 
>> Since playgrounds are always compiled from source, the fact that this would 
>> be an ABI change for PlaygroundSupport does not matter, and a compatibility 
>> typealias could be provided in PlaygroundSupport to maintain compatibility 
>> with code which explicitly qualified the name of the 
>> CustomPlaygroundRepresentable protocol.
>> 
>>  
>> <https://github.com/cwakamo/swift-evolution/tree/playground-quicklook-api-revamp#have-customplaygroundrepresentable-return-something-other-than-any>Have
>>  CustomPlaygroundRepresentable return something other than Any?
>> 
>> One minor alternative considered was to have CustomPlaygroundRepresentable 
>> return a value with a more specific type than Any?. For example:
>> 
>> protocol CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: CustomPlaygroundRepresentable? { get }
>> }
>> or:
>> 
>> protocol PlaygroundRepresentation {}
>> 
>> protocol CustomPlaygroundRepresentable {
>>   var playgroundRepresentation: PlaygroundRepresentation? { get }
>> }
>> In both cases, core types which the playground logger supports would conform 
>> to the appropriate protocol such that they could be returned from 
>> implementations of playgroundRepresentation.
>> 
>> The benefit to this approach is that it is more self-documenting than the 
>> approach proposed in this document, as a user can look up all of the types 
>> which conform to a particular protocol to know what the playground logger 
>> understands. However, this approach has a number of pitfalls, largely 
>> because it's intentional that the proposal uses Any instead of a 
>> more-constrained protocol. It should be possible to return anything as the 
>> stand-in for an instance, including values without opaque playground quick 
>> look views, so that it's easier to construct an alternate structured view of 
>> a type (without having to override the more complex CustomReflectable 
>> protocol). Furthermore, by making the API in the library use a general type 
>> like Any, this proposal prevents revlock from occurring between IDEs and the 
>> libraries, as the IDE's playground logger can implement support for opaque 
>> logging of new types without requiring library changes. (And IDEs can opt to 
>> support a subset of types if they prefer, whereas if the libraries promised 
>> support an IDE would effectively be compelled to provide it.)
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to