Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-17 Thread Chris Lattner via swift-evolution
SGTM!

-Chris

> On Jan 17, 2018, at 3:14 PM, Connor Wakamo  wrote:
> 
> 
> 
>> On Jan 12, 2018, at 11:02 PM, Chris Lattner > > wrote:
>> 
>>> On Jan 12, 2018, at 6:22 PM, Connor Wakamo >> > wrote:
>>> 
> The second case, and the one I’m more worried about, is subclassing. If, 
> for instance, you have the following:
> 
>   class FooView: UIView, CustomPlaygroundRepresentable {
>   var playgroundRepresentation: Any {
>   return “A string describing this view"
>   }
>   }
> 
>   class BarView: FooView {
>   override var playgroundRepresentation: Any {
>   // BarView instances wanted to be logged as themselves, 
> but there’s no way to express that
>   return ???
>   }
>   }
> 
> There’s nothing that BarView can do to ensure it gets logged like a view 
> because FooView declared a conformance to CustomPlaygroundRepresentable.
 
 I really don’t understand this.  FooView declares that it conforms, and it 
 provides a “playgroundRepresentation” member.  Cool for FooView.
 
 BarView comes around and overrides FooView’s implementation.  They don’t 
 have to conform, because it *isa* FooView, so of course it conforms.  If 
 it wants to customize its presentation, it overrides its  
 “playgroundRepresentation” method and it… just works.  If it conditionally 
 wants the FooView representation for some reason, it can even call 
 “super.playgroundRepresentation”.  What’s the problem?  This seems ideal 
 to me.
>>> 
>>> The issue is that there’s no way for `BarView` to recover the default 
>>> playground representation which `UIView` and its subclasses get.
>> 
>> I get it now, thanks.
>> 
>>> For a `UIView`, the PlaygroundLogger library renders an image of the view 
>>> and packages that up in a log entry. If `BarView` wants that instead of 
>>> `FooView`’s custom representation, there’s no way for it to request it.
>> 
>> I can think of two different ways to solve this problem:
>> 
>> 1) Go with your suggestion upthread, where a custom enum is used: 
>> implementations do:
>> 
>>   if predicate() {
>> return .custom(“my representation)
>>   } else {
>> return .default
>>   }
>> 
>> The problem with this is that you’re forcing implementations of this to deal 
>> with the enum just because of the rare case.  Not a showstopper, but doesn’t 
>> feel right.
>> 
>> 2) Go with the simple approach of returning Any, and add a new function to 
>> the Playground API somewhere that produces the default representation that 
>> they can call, the unusual case above would look like this:
>> 
>>   if predicate() {
>> return “my representation
>>   } else {
>> return SomePlaygroundAPI.getDefaultPlaygroundRepresentation(self)
>>   }
>> 
>> This seems like the best of both worlds to me.
> 
> Yes, agreed. I’m not going to propose adding this to PlaygroundSupport as 
> part of this proposal (under the assumption that this is an extreme edge case 
> to begin with), but I’ll include a reference to it in the “alternatives 
> considered” section so it can be referenced in the future should this be 
> important enough that it warrants support.
> 
 IMO, every time you choose to privilege “well known” types in the standard 
 library with special code in Xcode (or some other high level system 
 loosely integrated with swift.org ) you are introducing 
 technical debt into the Swift ecosystem.  This is because you are 
 violating the basic principles on which Swift was established, which is 
 that users can [re]define primitives to build their own abstractions and 
 carve out new domains beyond what was originally envisioned when you’re 
 writing the UI code.
>>> 
>>> So given that, I think it’s not unreasonable for a platform/toolchain’s 
>>> playground logger to know about that platform/toolchain’s important types 
>>> so it can produce the appropriate opaque log entries. If there’s some 
>>> approach that I’m overlooking — or if I’m dismissing the suite of protocols 
>>> case too quickly — I would love to hear it, because I’m open to suggestions.
>> 
>> Yes, you are completely right: Unless you are willing to make the structured 
>> schema public, there is no point to doing what I suggest.
>> 
>> I do think that there is a schema which would make sense to take public 
>> (similar to the abstract format used in treeviews like the navigator and UI 
>> debugger for variables, strikingly similar to what JSON can express with a 
>> fancier terminal than strings), but there is no rush to do that, and it is 
>> best to take time to consider it deliberately.
> 
> Likewise, agreed — I don’t want to try to figure out what that would look 
> like with the time pressure imposed 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-17 Thread Connor Wakamo via swift-evolution


> On Jan 13, 2018, at 2:18 PM, Erica Sadun  wrote:
> 
> On Jan 11, 2018, at 1:40 PM, Jonathan Hull via swift-evolution 
> > wrote:
>> 
>> 
>>> On Jan 11, 2018, at 11:22 AM, Connor Wakamo via swift-evolution 
>>> > wrote:
>>> 
>>> That’s very reasonable. I’ll update the proposal to use 
>>> CustomPlaygroundConvertible (unless I or someone else can come up with a 
>>> really good “Thing” for a name like CustomPlaygroundThingConvertible, as 
>>> that would even better match 
>>> CustomStringConvertible/CustomDebugStringConvertible).
>> 
>> CustomPlaygroundPreviewConvertible?
> 
> I'm a heavy user of `CustomPlaygroundQuickLookable` (for example, 
> https://i.imgur.com/zOa5OUZ.jpg ).  Although 
> I'm happy with the current name, to make it more in line with other 
> convertibles, perhaps:
> 
> * CustomPlaygroundQuickLookConvertible
> * CustomPlaygroundDisplayConvertible
> * CustomPlaygroundValuePresentationConvertible
> * CustomPlaygroundPresentationConvertible

Using the existing name for the new protocol isn’t on the table, as that would 
present a source compatibility issue which we couldn’t paper over. These names 
are interesting; I’ll at the very least include them in “alternatives 
considered” in my updated proposal.

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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-17 Thread Connor Wakamo via swift-evolution


> On Jan 13, 2018, at 8:20 AM, Karl Wagner  wrote:
> 
> 
> 
>> On 13. Jan 2018, at 03:22, Connor Wakamo via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On Jan 11, 2018, at 11:51 PM, Chris Lattner >> > wrote:
>>> 
>>> On Jan 11, 2018, at 11:22 AM, Connor Wakamo >> > wrote:
>> 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.
> 
> Which cases?  How important are they?
 
 I can think of a couple of cases where this could be useful.
 
 The first is an enum. Extending Riley’s example from earlier in the thread:
 
enum MyUnion {
case string(String)
case image(UIImage)
case intPair(Int, Int)
case none
}
 
 This enum might want to present the string and image cases as strings and 
 images, but treat the intPair and none cases the “default” way for the 
 enum. This is probably not the most compelling example as there is a 
 workaround — return a second enum or other structured type from 
 playgroundRepresentation — but that feels not great.
>>> 
>>> IMO, this is sugaring something that doesn’t need to be sugared.  There are 
>>> simple solutions to this problem without complicating the design of your 
>>> feature.  The few people who care about this can write it out long hand.
>> 
>> Agreed.
>> 
 The second case, and the one I’m more worried about, is subclassing. If, 
 for instance, you have the following:
 
class FooView: UIView, CustomPlaygroundRepresentable {
var playgroundRepresentation: Any {
return “A string describing this view"
}
}
 
class BarView: FooView {
override var playgroundRepresentation: Any {
// BarView instances wanted to be logged as themselves, 
 but there’s no way to express that
return ???
}
}
 
 There’s nothing that BarView can do to ensure it gets logged like a view 
 because FooView declared a conformance to CustomPlaygroundRepresentable.
>>> 
>>> I really don’t understand this.  FooView declares that it conforms, and it 
>>> provides a “playgroundRepresentation” member.  Cool for FooView.
>>> 
>>> BarView comes around and overrides FooView’s implementation.  They don’t 
>>> have to conform, because it *isa* FooView, so of course it conforms.  If it 
>>> wants to customize its presentation, it overrides its  
>>> “playgroundRepresentation” method and it… just works.  If it conditionally 
>>> wants the FooView representation for some reason, it can even call 
>>> “super.playgroundRepresentation”.  What’s the problem?  This seems ideal to 
>>> me.
>> 
>> The issue is that there’s no way for `BarView` to recover the default 
>> playground representation which `UIView` and its subclasses get. For a 
>> `UIView`, the PlaygroundLogger library renders an image of the view and 
>> packages that up in a log entry. If `BarView` wants that instead of 
>> `FooView`’s custom representation, there’s no way for it to request it.
>> 
>> That being said, I think I’m convinced that this is enough of an edge case 
>> that shouldn’t complicate the design of the protocol. So in my updated 
>> proposal I’ll be going with:
>> 
>>  protocol CustomPlaygroundConvertible {
>>  var playgroundDescription: Any { get }
>>  }
>> 
>> If we find out that this isn’t as much of an edge case as thought, we can 
>> add a type like `DefaultPlaygroundRepresentation` to 
>> PlaygroundSupport which would signal to the playground logger that it should 
>> log the wrapped type but without considering a `CustomPlaygroundConvertible` 
>> conformance.
> 
> (Replying to future comments as well here): so the hierarchy looks like: 
> NSObject -> UIView -> FooView -> BarView, and we’re saying that BarView 
> should be able to override FooView’s override and drop down one of its 
> ancestors implementations?
> 
> IMO, the only way to do this is to return “super.super.playgroundDescription” 
> (if BarView wants to present as a UIView) or 
> “super.super.super.playgroundDescription” (if it wants to present as an 
> NSObject — imagine NSObject had some custom representation).
> 
> If it just returned “.default”, how would the logger know which superclass 
> implementation to use (UIView or NSObject)?

My answer to this is a bit of a deflection — this isn’t a case PlaygroundLogger 
currently has to worry about, as it’s “natively-supported” opaquely-represented 
types don’t have any common typing, aside from NSObject which isn’t 
opaquely-represented. But it does mean that if we 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-17 Thread Connor Wakamo via swift-evolution


> On Jan 12, 2018, at 11:02 PM, Chris Lattner  wrote:
> 
>> On Jan 12, 2018, at 6:22 PM, Connor Wakamo > > wrote:
>> 
 The second case, and the one I’m more worried about, is subclassing. If, 
 for instance, you have the following:
 
class FooView: UIView, CustomPlaygroundRepresentable {
var playgroundRepresentation: Any {
return “A string describing this view"
}
}
 
class BarView: FooView {
override var playgroundRepresentation: Any {
// BarView instances wanted to be logged as themselves, 
 but there’s no way to express that
return ???
}
}
 
 There’s nothing that BarView can do to ensure it gets logged like a view 
 because FooView declared a conformance to CustomPlaygroundRepresentable.
>>> 
>>> I really don’t understand this.  FooView declares that it conforms, and it 
>>> provides a “playgroundRepresentation” member.  Cool for FooView.
>>> 
>>> BarView comes around and overrides FooView’s implementation.  They don’t 
>>> have to conform, because it *isa* FooView, so of course it conforms.  If it 
>>> wants to customize its presentation, it overrides its  
>>> “playgroundRepresentation” method and it… just works.  If it conditionally 
>>> wants the FooView representation for some reason, it can even call 
>>> “super.playgroundRepresentation”.  What’s the problem?  This seems ideal to 
>>> me.
>> 
>> The issue is that there’s no way for `BarView` to recover the default 
>> playground representation which `UIView` and its subclasses get.
> 
> I get it now, thanks.
> 
>> For a `UIView`, the PlaygroundLogger library renders an image of the view 
>> and packages that up in a log entry. If `BarView` wants that instead of 
>> `FooView`’s custom representation, there’s no way for it to request it.
> 
> I can think of two different ways to solve this problem:
> 
> 1) Go with your suggestion upthread, where a custom enum is used: 
> implementations do:
> 
>   if predicate() {
> return .custom(“my representation)
>   } else {
> return .default
>   }
> 
> The problem with this is that you’re forcing implementations of this to deal 
> with the enum just because of the rare case.  Not a showstopper, but doesn’t 
> feel right.
> 
> 2) Go with the simple approach of returning Any, and add a new function to 
> the Playground API somewhere that produces the default representation that 
> they can call, the unusual case above would look like this:
> 
>   if predicate() {
> return “my representation
>   } else {
> return SomePlaygroundAPI.getDefaultPlaygroundRepresentation(self)
>   }
> 
> This seems like the best of both worlds to me.

Yes, agreed. I’m not going to propose adding this to PlaygroundSupport as part 
of this proposal (under the assumption that this is an extreme edge case to 
begin with), but I’ll include a reference to it in the “alternatives 
considered” section so it can be referenced in the future should this be 
important enough that it warrants support.

>>> IMO, every time you choose to privilege “well known” types in the standard 
>>> library with special code in Xcode (or some other high level system loosely 
>>> integrated with swift.org ) you are introducing 
>>> technical debt into the Swift ecosystem.  This is because you are violating 
>>> the basic principles on which Swift was established, which is that users 
>>> can [re]define primitives to build their own abstractions and carve out new 
>>> domains beyond what was originally envisioned when you’re writing the UI 
>>> code.
>> 
>> So given that, I think it’s not unreasonable for a platform/toolchain’s 
>> playground logger to know about that platform/toolchain’s important types so 
>> it can produce the appropriate opaque log entries. If there’s some approach 
>> that I’m overlooking — or if I’m dismissing the suite of protocols case too 
>> quickly — I would love to hear it, because I’m open to suggestions.
> 
> Yes, you are completely right: Unless you are willing to make the structured 
> schema public, there is no point to doing what I suggest.
> 
> I do think that there is a schema which would make sense to take public 
> (similar to the abstract format used in treeviews like the navigator and UI 
> debugger for variables, strikingly similar to what JSON can express with a 
> fancier terminal than strings), but there is no rush to do that, and it is 
> best to take time to consider it deliberately.

Likewise, agreed — I don’t want to try to figure out what that would look like 
with the time pressure imposed by trying to get this in Swift 4.1 prior to ABI 
stability. And even in a world where this is exposed in a way to allow custom 
implementations at that low level, I think that a 
`CustomPlaygroundConvertible`-style API is still 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-13 Thread Erica Sadun via swift-evolution
Perhaps bring the three special case literals into this as well? (File, image, 
color)

-- E

> On Jan 9, 2018, at 4:53 PM, Ben Cohen via swift-evolution 
>  wrote:
> 
> Big +1 to this. Getting these types out of the standard library and into a 
> more suitable domain-specific framework, prior to declaring ABI Stability, 
> will give us flexibility to evolve them appropriately over time.
> 
>> On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
>> > 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- 
>> 
>> Authors: Connor Wakamo 
>> Review Manager: TBD
>> Status: Awaiting implementation
>>  
>> 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 
>> 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-13 Thread Karl Wagner via swift-evolution


> On 13. Jan 2018, at 03:22, Connor Wakamo via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 11, 2018, at 11:51 PM, Chris Lattner > > wrote:
>> 
>> On Jan 11, 2018, at 11:22 AM, Connor Wakamo > > wrote:
> 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.
 
 Which cases?  How important are they?
>>> 
>>> I can think of a couple of cases where this could be useful.
>>> 
>>> The first is an enum. Extending Riley’s example from earlier in the thread:
>>> 
>>> enum MyUnion {
>>> case string(String)
>>> case image(UIImage)
>>> case intPair(Int, Int)
>>> case none
>>> }
>>> 
>>> This enum might want to present the string and image cases as strings and 
>>> images, but treat the intPair and none cases the “default” way for the 
>>> enum. This is probably not the most compelling example as there is a 
>>> workaround — return a second enum or other structured type from 
>>> playgroundRepresentation — but that feels not great.
>> 
>> IMO, this is sugaring something that doesn’t need to be sugared.  There are 
>> simple solutions to this problem without complicating the design of your 
>> feature.  The few people who care about this can write it out long hand.
> 
> Agreed.
> 
>>> The second case, and the one I’m more worried about, is subclassing. If, 
>>> for instance, you have the following:
>>> 
>>> class FooView: UIView, CustomPlaygroundRepresentable {
>>> var playgroundRepresentation: Any {
>>> return “A string describing this view"
>>> }
>>> }
>>> 
>>> class BarView: FooView {
>>> override var playgroundRepresentation: Any {
>>> // BarView instances wanted to be logged as themselves, 
>>> but there’s no way to express that
>>> return ???
>>> }
>>> }
>>> 
>>> There’s nothing that BarView can do to ensure it gets logged like a view 
>>> because FooView declared a conformance to CustomPlaygroundRepresentable.
>> 
>> I really don’t understand this.  FooView declares that it conforms, and it 
>> provides a “playgroundRepresentation” member.  Cool for FooView.
>> 
>> BarView comes around and overrides FooView’s implementation.  They don’t 
>> have to conform, because it *isa* FooView, so of course it conforms.  If it 
>> wants to customize its presentation, it overrides its  
>> “playgroundRepresentation” method and it… just works.  If it conditionally 
>> wants the FooView representation for some reason, it can even call 
>> “super.playgroundRepresentation”.  What’s the problem?  This seems ideal to 
>> me.
> 
> The issue is that there’s no way for `BarView` to recover the default 
> playground representation which `UIView` and its subclasses get. For a 
> `UIView`, the PlaygroundLogger library renders an image of the view and 
> packages that up in a log entry. If `BarView` wants that instead of 
> `FooView`’s custom representation, there’s no way for it to request it.
> 
> That being said, I think I’m convinced that this is enough of an edge case 
> that shouldn’t complicate the design of the protocol. So in my updated 
> proposal I’ll be going with:
> 
>   protocol CustomPlaygroundConvertible {
>   var playgroundDescription: Any { get }
>   }
> 
> If we find out that this isn’t as much of an edge case as thought, we can add 
> a type like `DefaultPlaygroundRepresentation` to PlaygroundSupport 
> which would signal to the playground logger that it should log the wrapped 
> type but without considering a `CustomPlaygroundConvertible` conformance.

(Replying to future comments as well here): so the hierarchy looks like: 
NSObject -> UIView -> FooView -> BarView, and we’re saying that BarView should 
be able to override FooView’s override and drop down one of its ancestors 
implementations?

IMO, the only way to do this is to return “super.super.playgroundDescription” 
(if BarView wants to present as a UIView) or 
“super.super.super.playgroundDescription” (if it wants to present as an 
NSObject — imagine NSObject had some custom representation).

If it just returned “.default”, how would the logger know which superclass 
implementation to use (UIView or NSObject)?

> 
> 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 swift-xcode-playground-support 
> ) to recognize 
> these types and handle them accordingly. The playground logger would look 
> through the 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-12 Thread Chris Lattner via swift-evolution
> On Jan 12, 2018, at 6:22 PM, Connor Wakamo  wrote:
> 
>>> The second case, and the one I’m more worried about, is subclassing. If, 
>>> for instance, you have the following:
>>> 
>>> class FooView: UIView, CustomPlaygroundRepresentable {
>>> var playgroundRepresentation: Any {
>>> return “A string describing this view"
>>> }
>>> }
>>> 
>>> class BarView: FooView {
>>> override var playgroundRepresentation: Any {
>>> // BarView instances wanted to be logged as themselves, 
>>> but there’s no way to express that
>>> return ???
>>> }
>>> }
>>> 
>>> There’s nothing that BarView can do to ensure it gets logged like a view 
>>> because FooView declared a conformance to CustomPlaygroundRepresentable.
>> 
>> I really don’t understand this.  FooView declares that it conforms, and it 
>> provides a “playgroundRepresentation” member.  Cool for FooView.
>> 
>> BarView comes around and overrides FooView’s implementation.  They don’t 
>> have to conform, because it *isa* FooView, so of course it conforms.  If it 
>> wants to customize its presentation, it overrides its  
>> “playgroundRepresentation” method and it… just works.  If it conditionally 
>> wants the FooView representation for some reason, it can even call 
>> “super.playgroundRepresentation”.  What’s the problem?  This seems ideal to 
>> me.
> 
> The issue is that there’s no way for `BarView` to recover the default 
> playground representation which `UIView` and its subclasses get.

I get it now, thanks.

> For a `UIView`, the PlaygroundLogger library renders an image of the view and 
> packages that up in a log entry. If `BarView` wants that instead of 
> `FooView`’s custom representation, there’s no way for it to request it.

I can think of two different ways to solve this problem:

1) Go with your suggestion upthread, where a custom enum is used: 
implementations do:

  if predicate() {
return .custom(“my representation)
  } else {
return .default
  }

The problem with this is that you’re forcing implementations of this to deal 
with the enum just because of the rare case.  Not a showstopper, but doesn’t 
feel right.

2) Go with the simple approach of returning Any, and add a new function to the 
Playground API somewhere that produces the default representation that they can 
call, the unusual case above would look like this:

  if predicate() {
return “my representation
  } else {
return SomePlaygroundAPI.getDefaultPlaygroundRepresentation(self)
  }

This seems like the best of both worlds to me.

>> IMO, every time you choose to privilege “well known” types in the standard 
>> library with special code in Xcode (or some other high level system loosely 
>> integrated with swift.org ) you are introducing technical 
>> debt into the Swift ecosystem.  This is because you are violating the basic 
>> principles on which Swift was established, which is that users can 
>> [re]define primitives to build their own abstractions and carve out new 
>> domains beyond what was originally envisioned when you’re writing the UI 
>> code.
> 
> So given that, I think it’s not unreasonable for a platform/toolchain’s 
> playground logger to know about that platform/toolchain’s important types so 
> it can produce the appropriate opaque log entries. If there’s some approach 
> that I’m overlooking — or if I’m dismissing the suite of protocols case too 
> quickly — I would love to hear it, because I’m open to suggestions.

Yes, you are completely right: Unless you are willing to make the structured 
schema public, there is no point to doing what I suggest.

I do think that there is a schema which would make sense to take public 
(similar to the abstract format used in treeviews like the navigator and UI 
debugger for variables, strikingly similar to what JSON can express with a 
fancier terminal than strings), but there is no rush to do that, and it is best 
to take time to consider it deliberately.


>> Is the problem the “one” case?  If that is the problem, then it might be 
>> better to take a completely different approach where you embrace the fact 
>> that you have structured data producing 2D results that need to be 
>> displayed.  Each result could either return an atomic result or a result 
>> that wraps some other recursive 2D presentation.
> 
> No, the issue is that the playground logger would see that `Foo.two` conforms 
> to `CustomPlaygroundConvertible`, and would therefore call 
> `playgroundDescription` another time, which would return another `Foo.two`, 
> and this would continue endlessly. I plan to guard against that in 
> PlaygroundLogger with a limit on chaining, but this protocol should not 
> require a failsafe as a feature.

Right, it seems like the best way to solve this is to provide explicit access 
to the default presentation.

-Chris


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-12 Thread Connor Wakamo via swift-evolution


> On Jan 11, 2018, at 11:51 PM, Chris Lattner  wrote:
> 
> On Jan 11, 2018, at 11:22 AM, Connor Wakamo  > wrote:
 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.
>>> 
>>> Which cases?  How important are they?
>> 
>> I can think of a couple of cases where this could be useful.
>> 
>> The first is an enum. Extending Riley’s example from earlier in the thread:
>> 
>>  enum MyUnion {
>>  case string(String)
>>  case image(UIImage)
>>  case intPair(Int, Int)
>>  case none
>>  }
>> 
>> This enum might want to present the string and image cases as strings and 
>> images, but treat the intPair and none cases the “default” way for the enum. 
>> This is probably not the most compelling example as there is a workaround — 
>> return a second enum or other structured type from playgroundRepresentation 
>> — but that feels not great.
> 
> IMO, this is sugaring something that doesn’t need to be sugared.  There are 
> simple solutions to this problem without complicating the design of your 
> feature.  The few people who care about this can write it out long hand.

Agreed.

>> The second case, and the one I’m more worried about, is subclassing. If, for 
>> instance, you have the following:
>> 
>>  class FooView: UIView, CustomPlaygroundRepresentable {
>>  var playgroundRepresentation: Any {
>>  return “A string describing this view"
>>  }
>>  }
>> 
>>  class BarView: FooView {
>>  override var playgroundRepresentation: Any {
>>  // BarView instances wanted to be logged as themselves, 
>> but there’s no way to express that
>>  return ???
>>  }
>>  }
>> 
>> There’s nothing that BarView can do to ensure it gets logged like a view 
>> because FooView declared a conformance to CustomPlaygroundRepresentable.
> 
> I really don’t understand this.  FooView declares that it conforms, and it 
> provides a “playgroundRepresentation” member.  Cool for FooView.
> 
> BarView comes around and overrides FooView’s implementation.  They don’t have 
> to conform, because it *isa* FooView, so of course it conforms.  If it wants 
> to customize its presentation, it overrides its  “playgroundRepresentation” 
> method and it… just works.  If it conditionally wants the FooView 
> representation for some reason, it can even call 
> “super.playgroundRepresentation”.  What’s the problem?  This seems ideal to 
> me.

The issue is that there’s no way for `BarView` to recover the default 
playground representation which `UIView` and its subclasses get. For a 
`UIView`, the PlaygroundLogger library renders an image of the view and 
packages that up in a log entry. If `BarView` wants that instead of `FooView`’s 
custom representation, there’s no way for it to request it.

That being said, I think I’m convinced that this is enough of an edge case that 
shouldn’t complicate the design of the protocol. So in my updated proposal I’ll 
be going with:

protocol CustomPlaygroundConvertible {
var playgroundDescription: Any { get }
}

If we find out that this isn’t as much of an edge case as thought, we can add a 
type like `DefaultPlaygroundRepresentation` to PlaygroundSupport which 
would signal to the playground logger that it should log the wrapped type but 
without considering a `CustomPlaygroundConvertible` conformance.

 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 swift-xcode-playground-support 
 ) 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`.
>>> 
>>> Why not?  I understand that that is how the old algorithm worked, but it 
>>> contained a lot of special case hacks due to the state of Swift 1 :-).  
>>> This is a chance to dissolve those away.
>> 
>> It’s a feature that Optional (and other standard library/corelibs/OS types) 
>> don’t conform to CustomPlaygroundRepresentable. In my mind, it’s the role of 
>> the PlaygroundLogger library to understand the types for which it wishes to 
>> generate an opaque representation instead of the standard/fallback 
>> structured representation. So Optional, String, Int, UIColor, NSView, etc. 
>> don’t themselves conform to CustomPlaygroundRepresentable — they’re not 
>> customizing their 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-11 Thread Chris Lattner via swift-evolution
On Jan 11, 2018, at 11:22 AM, Connor Wakamo  wrote:
>>> 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.
>> 
>> Which cases?  How important are they?
> 
> I can think of a couple of cases where this could be useful.
> 
> The first is an enum. Extending Riley’s example from earlier in the thread:
> 
>   enum MyUnion {
>   case string(String)
>   case image(UIImage)
>   case intPair(Int, Int)
>   case none
>   }
> 
> This enum might want to present the string and image cases as strings and 
> images, but treat the intPair and none cases the “default” way for the enum. 
> This is probably not the most compelling example as there is a workaround — 
> return a second enum or other structured type from playgroundRepresentation — 
> but that feels not great.

IMO, this is sugaring something that doesn’t need to be sugared.  There are 
simple solutions to this problem without complicating the design of your 
feature.  The few people who care about this can write it out long hand.

> The second case, and the one I’m more worried about, is subclassing. If, for 
> instance, you have the following:
> 
>   class FooView: UIView, CustomPlaygroundRepresentable {
>   var playgroundRepresentation: Any {
>   return “A string describing this view"
>   }
>   }
> 
>   class BarView: FooView {
>   override var playgroundRepresentation: Any {
>   // BarView instances wanted to be logged as themselves, 
> but there’s no way to express that
>   return ???
>   }
>   }
> 
> There’s nothing that BarView can do to ensure it gets logged like a view 
> because FooView declared a conformance to CustomPlaygroundRepresentable.

I really don’t understand this.  FooView declares that it conforms, and it 
provides a “playgroundRepresentation” member.  Cool for FooView.

BarView comes around and overrides FooView’s implementation.  They don’t have 
to conform, because it *isa* FooView, so of course it conforms.  If it wants to 
customize its presentation, it overrides its  “playgroundRepresentation” method 
and it… just works.  If it conditionally wants the FooView representation for 
some reason, it can even call “super.playgroundRepresentation”.  What’s the 
problem?  This seems ideal to me.

>>> 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 swift-xcode-playground-support 
>>> ) 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`.
>> 
>> Why not?  I understand that that is how the old algorithm worked, but it 
>> contained a lot of special case hacks due to the state of Swift 1 :-).  This 
>> is a chance to dissolve those away.
> 
> It’s a feature that Optional (and other standard library/corelibs/OS types) 
> don’t conform to CustomPlaygroundRepresentable. In my mind, it’s the role of 
> the PlaygroundLogger library to understand the types for which it wishes to 
> generate an opaque representation instead of the standard/fallback structured 
> representation. So Optional, String, Int, UIColor, NSView, etc. don’t 
> themselves conform to CustomPlaygroundRepresentable — they’re not customizing 
> their presentation in a playground.

IMO, this was the right Swift 1 attitude: "make it work at all costs" but this 
is not the right approach for Swift over the long term, and not the right 
answer for Swift 5 in particular.

Swift is still very young and immature in some ways, but it it is intentionally 
design for extensibility and to be used in surprising and delightful ways.  It 
isn’t an accident of history that Int and Bool are defined in the standard 
library instead of being burned into the compiler.

IMO, every time you choose to privilege “well known” types in the standard 
library with special code in Xcode (or some other high level system loosely 
integrated with swift.org) you are introducing technical debt into the Swift 
ecosystem.  This is because you are violating the basic principles on which 
Swift was established, which is that users can [re]define primitives to build 
their own abstractions and carve out new domains beyond what was originally 
envisioned when you’re writing the UI code.

> Semi-related to this proposal, I’m working on a rewrite of the 
> PlaygroundLogger library (currently at 
> 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-11 Thread Saagar Jha via swift-evolution
CustomPlaygroundRepresentationConvertible?

Saagar Jha

> On Jan 11, 2018, at 11:22, Connor Wakamo via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 10, 2018, at 4:21 PM, Chris Lattner > > wrote:
>> 
>>> On Jan 10, 2018, at 2:10 PM, Connor Wakamo >> > wrote:
 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?
>>> 
>>> 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.
>> 
>> Right, this gets back to the question: what is the use case for this?  When 
>> would a type want to “sometimes” replace the default representation?
>> 
>> It seems to me that a type author either wants to take control of 
>> presentation or not.  While I’m sure we could imagine some use case for the 
>> behavior you’re describing, is it big enough to make it worth complicating 
>> the API?
>> 
>>> 
>>> 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`). 
>> 
>> Ok
>> 
 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.  :-)
>>> 
>>> 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.
>> 
>> Which cases?  How important are they?
> 
> I can think of a couple of cases where this could be useful.
> 
> The first is an enum. Extending Riley’s example from earlier in the thread:
> 
>   enum MyUnion {
>   case string(String)
>   case image(UIImage)
>   case intPair(Int, Int)
>   case none
>   }
> 
> This enum might want to present the string and image cases as strings and 
> images, but treat the intPair and none cases the “default” way for the enum. 
> This is probably not the most compelling example as there is a workaround — 
> return a second enum or other structured type from playgroundRepresentation — 
> but that feels not great.
> 
> The second case, and the one I’m more worried about, is subclassing. If, for 
> instance, you have the following:
> 
>   class FooView: UIView, CustomPlaygroundRepresentable {
>   var playgroundRepresentation: Any {
>   return “A string describing this view"
>   }
>   }
> 
>   class BarView: FooView {
>   override var playgroundRepresentation: Any {
>   // BarView instances wanted to be logged as themselves, 
> but there’s no way to express that
>   return ???
>   }
>   }
> 
> There’s nothing that BarView can do to ensure it gets logged like a view 
> because FooView declared a conformance to CustomPlaygroundRepresentable.
> 
> I’m not sure how important these cases are. If it were just the first one, 
> I’d probably say we can safely ignore it because there’s a reasonable 
> workaround. But the subclassing case worries me because there’s no escape 
> hatch (aside from a potential implementation-defined failsafe).
> 
> 
>>> 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 swift-xcode-playground-support 
>>> ) 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`.
>> 
>> Why not?  I understand that that is how the old algorithm worked, but it 
>> contained a lot of special case hacks due to the state of Swift 1 :-).  This 
>> is a chance to dissolve those away.
> 
> It’s a feature that Optional (and other standard library/corelibs/OS types) 
> don’t conform to CustomPlaygroundRepresentable. In my mind, it’s the role of 
> the PlaygroundLogger library to understand the types for which it wishes to 
> generate an opaque representation instead of the standard/fallback structured 
> representation. So Optional, String, Int, UIColor, NSView, etc. don’t 
> themselves conform to CustomPlaygroundRepresentable — they’re not customizing 
> their 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-11 Thread Jonathan Hull via swift-evolution

> On Jan 11, 2018, at 11:22 AM, Connor Wakamo via swift-evolution 
>  wrote:
> 
> That’s very reasonable. I’ll update the proposal to use 
> CustomPlaygroundConvertible (unless I or someone else can come up with a 
> really good “Thing” for a name like CustomPlaygroundThingConvertible, as that 
> would even better match CustomStringConvertible/CustomDebugStringConvertible).

CustomPlaygroundPreviewConvertible?___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-11 Thread Connor Wakamo via swift-evolution


> On Jan 10, 2018, at 4:21 PM, Chris Lattner  wrote:
> 
>> On Jan 10, 2018, at 2:10 PM, Connor Wakamo > > wrote:
>>> 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?
>> 
>> 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.
> 
> Right, this gets back to the question: what is the use case for this?  When 
> would a type want to “sometimes” replace the default representation?
> 
> It seems to me that a type author either wants to take control of 
> presentation or not.  While I’m sure we could imagine some use case for the 
> behavior you’re describing, is it big enough to make it worth complicating 
> the API?
> 
>> 
>> 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`).
> 
> Ok
> 
>>> 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.  :-)
>> 
>> 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.
> 
> Which cases?  How important are they?

I can think of a couple of cases where this could be useful.

The first is an enum. Extending Riley’s example from earlier in the thread:

enum MyUnion {
case string(String)
case image(UIImage)
case intPair(Int, Int)
case none
}

This enum might want to present the string and image cases as strings and 
images, but treat the intPair and none cases the “default” way for the enum. 
This is probably not the most compelling example as there is a workaround — 
return a second enum or other structured type from playgroundRepresentation — 
but that feels not great.

The second case, and the one I’m more worried about, is subclassing. If, for 
instance, you have the following:

class FooView: UIView, CustomPlaygroundRepresentable {
var playgroundRepresentation: Any {
return “A string describing this view"
}
}

class BarView: FooView {
override var playgroundRepresentation: Any {
// BarView instances wanted to be logged as themselves, 
but there’s no way to express that
return ???
}
}

There’s nothing that BarView can do to ensure it gets logged like a view 
because FooView declared a conformance to CustomPlaygroundRepresentable.

I’m not sure how important these cases are. If it were just the first one, I’d 
probably say we can safely ignore it because there’s a reasonable workaround. 
But the subclassing case worries me because there’s no escape hatch (aside from 
a potential implementation-defined failsafe).


>> 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 swift-xcode-playground-support 
>> ) 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`.
> 
> Why not?  I understand that that is how the old algorithm worked, but it 
> contained a lot of special case hacks due to the state of Swift 1 :-).  This 
> is a chance to dissolve those away.

It’s a feature that Optional (and other standard library/corelibs/OS types) 
don’t conform to CustomPlaygroundRepresentable. In my mind, it’s the role of 
the PlaygroundLogger library to understand the types for which it wishes to 
generate an opaque representation instead of the standard/fallback structured 
representation. So Optional, String, Int, UIColor, NSView, etc. don’t 
themselves conform to CustomPlaygroundRepresentable — they’re not customizing 
their presentation in a playground.

Semi-related to this proposal, I’m working on a rewrite of the PlaygroundLogger 
library (currently at 


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Chris Lattner via swift-evolution
> On Jan 10, 2018, at 2:10 PM, Connor Wakamo  wrote:
>> 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?
> 
> 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.

Right, this gets back to the question: what is the use case for this?  When 
would a type want to “sometimes” replace the default representation?

It seems to me that a type author either wants to take control of presentation 
or not.  While I’m sure we could imagine some use case for the behavior you’re 
describing, is it big enough to make it worth complicating the API?

> 
> 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`).

Ok

>> 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.  :-)
> 
> 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.

Which cases?  How important are they?

> 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 swift-xcode-playground-support 
> ) 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`.

Why not?  I understand that that is how the old algorithm worked, but it 
contained a lot of special case hacks due to the state of Swift 1 :-).  This is 
a chance to dissolve those away.

To be clear, I would expect that the conformance for optional would be defined 
in the playground module along with this protocol - it wouldn’t be defined in 
the standard library itself.

> 
> One possibility would be to change the API so that it returns an enum. 
> Imagine:
> 
>   enum PlaygroundLoggingBehavior {
>   /// Asks the playground logger to generate the standard logging 
> for `self`.
>   case standard
> 
>   /// Asks the playground logger to generate logging for the 
> given `Any` instead of `self`.
>   case custom(Any)
>   }
> 
>   protocol CustomPlaygroundLoggable {
>   /// Returns the `PlaygroundLoggingBehavior` to use for `self`.
>   var playgroundLoggingBehavior: PlaygroundLoggingBehavior { get }
>   }
> 
> (To Saagar’s point in another email — you could even add a `case none` to 
> PlaygroundLoggingBehavior to inhibit logging of a particular instance.)
> 
> `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.

I just don’t understand the usecase for “conditional customizing” at all.  By 
way of example, we don’t have the ability to do that with 
CustomStringConvertible.   What is different about this case?

> 
>>> /// 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 {
>> 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?
>> 
>> The only prior art for the word “Representable” in the standard library is 
>> RawRepresentable, which is quite a different concept.
>> 
>>>   /// 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 }
>> Again to align with 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Connor Wakamo via swift-evolution


> On Jan 10, 2018, at 2:34 PM, Saagar Jha  wrote:
> 
> 
> Saagar Jha
> 
>> On Jan 10, 2018, at 14:10, Connor Wakamo > > wrote:
>> 
>>> On Jan 10, 2018, at 12:39 PM, Saagar Jha >> > wrote:
>>> 
>>> Well, in my experience performance issues tend to come not from trying to 
>>> display a single object, but when you have an aggregation of many objects. 
>>> For example, displaying one Int is pretty lightweight, as is an [Int] with 
>>> a handful of elements, but displaying an [Int] with million elements is not 
>>> (this is assuming that collections will run the playgroundRepresentation on 
>>> their individual elements as they do currently). I don’t think the current 
>>> proposal can solve this issue as it’s pitched currently. (For those 
>>> curious, this doesn’t have a good solution today, either: the best 
>>> “solution” I’ve been able to come up with is to move performance-sensitive 
>>> out into a Playground’s Sources folder, which isn’t displayed.)
>> 
>> Yes, this proposal does not affect this case: the playground transform will 
>> still instrument all of the source code in the main source file. This 
>> proposal is merely about deprecating/removing a substandard API for 
>> controlling how values are presented in playgrounds with a better, more 
>> flexible one. (Though see my other reply to Chris where I present an 
>> alternative which could be extended to include support for disabling logging 
>> altogether for an instance.)
>> 
>>> Fundamentally, I don’t think it’s clear what the “default” value is 
>>> supposed to be: we already have three different interpretations of what it 
>>> could do: do literally nothing (i.e. display an empty representation), use 
>>> a superclass’s representation, or use a structural representation based on 
>>> whether the type is an enum, struct, class, etc. I think we need to clear 
>>> up what the default actually means (and if we even need it at all) before 
>>> we can proceed.
>> 
>> This API is a bit wishy-washy as to what the “default” is. That’s somewhat 
>> intentional — the default presentation of an arbitrary Swift value/object is 
>> defined by the IDE, not by an API in Swift. I think my terminology is a bit 
>> confused here, and I’ll try to address that in a revision of the proposal. 
>> Let me try to clarify this a bit:
>> 
>> The fundamental design of playgrounds is that the compiler will insert calls 
>> to a logging function which is effectively required to take an `Any`. So 
>> therefore every instance of every type must be loggable by the playground 
>> logger. The PlaygroundLogger framework in swift-xcode-playground-support 
>>  implements this by 
>> generating either structured log entries using `Mirror` or specialized, 
>> opaque (aka IDERepr) log entries. PlaygroundLogger will generate a 
>> structured log entry for most instances, but for instances of special types 
>> it knows about (e.g. String, Int, NSColor, UIView, etc.) it will generate an 
>> opaque log entry which an IDE can then consume and display as is appropriate.
>> 
>> The CustomPlaygroundRepresentable API I’ve proposed does exactly one thing: 
>> it allows instances of conforming types to provide an optional stand-in to 
>> be used by the playground logger. So PlaygroundLogger would handle the 
>> following cases thusly:
>> 
>>  - If a type conforms to CustomPlaygroundRepresentable and returns a 
>> non-nil value, PlaygroundLogger will generate the appropriate log entry for 
>> the returned value
>>  - If a type conforms to CustomPlaygroundRepresentable and returns nil, 
>> PlaygroundLogger will generate the appropriate log entry for `self`
>>  - If `self` is one of the types (or a subclass of one of the 
>> types) for which PlaygroundLogger generates an opaque entry, 
>> PlaygroundLogger will generate an opaque log entry
>>  - Otherwise, PlaygroundLogger will generate a structured log 
>> entry
> 
> Just wanted to make it totally clear here: is the superclass selected the one 
> that is the closest to the current type, or the one that is the most distant 
> parent? Referring back to the example I had further upthread:
> 
> class FooView: UIView {
>   override var playgroundRepresentation: Any? {
>   return “foo”
>   }
> }
> 
> class BarView: FooView {
>   override var playgroundRepresentation: Any? {
>   return nil
>   }
> }
> 
> Does BarView show up as a UIView, or a FooView? If it’s shown as a FooView, 
> then returning nil is superfluous: you can just not override 
> playgroundRepresentation and it’ll pick up the one from FooView.

Ah, so here’s what it would do: since BarView conforms to 
CustomPlaygroundRepresentable, the playground logger would get the 
playgroundRepresentation. Since playgroundRepresentation returned nil, 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Saagar Jha via swift-evolution

Saagar Jha

> On Jan 10, 2018, at 14:10, Connor Wakamo  wrote:
> 
>> On Jan 10, 2018, at 12:39 PM, Saagar Jha > > wrote:
>> 
>> Well, in my experience performance issues tend to come not from trying to 
>> display a single object, but when you have an aggregation of many objects. 
>> For example, displaying one Int is pretty lightweight, as is an [Int] with a 
>> handful of elements, but displaying an [Int] with million elements is not 
>> (this is assuming that collections will run the playgroundRepresentation on 
>> their individual elements as they do currently). I don’t think the current 
>> proposal can solve this issue as it’s pitched currently. (For those curious, 
>> this doesn’t have a good solution today, either: the best “solution” I’ve 
>> been able to come up with is to move performance-sensitive out into a 
>> Playground’s Sources folder, which isn’t displayed.)
> 
> Yes, this proposal does not affect this case: the playground transform will 
> still instrument all of the source code in the main source file. This 
> proposal is merely about deprecating/removing a substandard API for 
> controlling how values are presented in playgrounds with a better, more 
> flexible one. (Though see my other reply to Chris where I present an 
> alternative which could be extended to include support for disabling logging 
> altogether for an instance.)
> 
>> Fundamentally, I don’t think it’s clear what the “default” value is supposed 
>> to be: we already have three different interpretations of what it could do: 
>> do literally nothing (i.e. display an empty representation), use a 
>> superclass’s representation, or use a structural representation based on 
>> whether the type is an enum, struct, class, etc. I think we need to clear up 
>> what the default actually means (and if we even need it at all) before we 
>> can proceed.
> 
> This API is a bit wishy-washy as to what the “default” is. That’s somewhat 
> intentional — the default presentation of an arbitrary Swift value/object is 
> defined by the IDE, not by an API in Swift. I think my terminology is a bit 
> confused here, and I’ll try to address that in a revision of the proposal. 
> Let me try to clarify this a bit:
> 
> The fundamental design of playgrounds is that the compiler will insert calls 
> to a logging function which is effectively required to take an `Any`. So 
> therefore every instance of every type must be loggable by the playground 
> logger. The PlaygroundLogger framework in swift-xcode-playground-support 
>  implements this by 
> generating either structured log entries using `Mirror` or specialized, 
> opaque (aka IDERepr) log entries. PlaygroundLogger will generate a structured 
> log entry for most instances, but for instances of special types it knows 
> about (e.g. String, Int, NSColor, UIView, etc.) it will generate an opaque 
> log entry which an IDE can then consume and display as is appropriate.
> 
> The CustomPlaygroundRepresentable API I’ve proposed does exactly one thing: 
> it allows instances of conforming types to provide an optional stand-in to be 
> used by the playground logger. So PlaygroundLogger would handle the following 
> cases thusly:
> 
>   - If a type conforms to CustomPlaygroundRepresentable and returns a 
> non-nil value, PlaygroundLogger will generate the appropriate log entry for 
> the returned value
>   - If a type conforms to CustomPlaygroundRepresentable and returns nil, 
> PlaygroundLogger will generate the appropriate log entry for `self`
>   - If `self` is one of the types (or a subclass of one of the 
> types) for which PlaygroundLogger generates an opaque entry, PlaygroundLogger 
> will generate an opaque log entry
>   - Otherwise, PlaygroundLogger will generate a structured log 
> entry

Just wanted to make it totally clear here: is the superclass selected the one 
that is the closest to the current type, or the one that is the most distant 
parent? Referring back to the example I had further upthread:

class FooView: UIView {
override var playgroundRepresentation: Any? {
return “foo”
}
}

class BarView: FooView {
override var playgroundRepresentation: Any? {
return nil
}
}

Does BarView show up as a UIView, or a FooView? If it’s shown as a FooView, 
then returning nil is superfluous: you can just not override 
playgroundRepresentation and it’ll pick up the one from FooView.

> 
> This process if potentially recursive (likely up to an implementation-defined 
> limit): if `Foo: CustomPlaygroundRepresentable` and `Bar: 
> CustomPlaygroundRepresentable`, and a `Foo` instance returns an instance of 
> `Bar` from `playgroundRepresentation`, then the playground logger should 
> effectively log `self.playgroundRepresentation.playgroundRepresentation`.
> 
> Connor


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Connor Wakamo via swift-evolution
> On Jan 10, 2018, at 12:39 PM, Saagar Jha  wrote:
> 
> Well, in my experience performance issues tend to come not from trying to 
> display a single object, but when you have an aggregation of many objects. 
> For example, displaying one Int is pretty lightweight, as is an [Int] with a 
> handful of elements, but displaying an [Int] with million elements is not 
> (this is assuming that collections will run the playgroundRepresentation on 
> their individual elements as they do currently). I don’t think the current 
> proposal can solve this issue as it’s pitched currently. (For those curious, 
> this doesn’t have a good solution today, either: the best “solution” I’ve 
> been able to come up with is to move performance-sensitive out into a 
> Playground’s Sources folder, which isn’t displayed.)

Yes, this proposal does not affect this case: the playground transform will 
still instrument all of the source code in the main source file. This proposal 
is merely about deprecating/removing a substandard API for controlling how 
values are presented in playgrounds with a better, more flexible one. (Though 
see my other reply to Chris where I present an alternative which could be 
extended to include support for disabling logging altogether for an instance.)

> Fundamentally, I don’t think it’s clear what the “default” value is supposed 
> to be: we already have three different interpretations of what it could do: 
> do literally nothing (i.e. display an empty representation), use a 
> superclass’s representation, or use a structural representation based on 
> whether the type is an enum, struct, class, etc. I think we need to clear up 
> what the default actually means (and if we even need it at all) before we can 
> proceed.

This API is a bit wishy-washy as to what the “default” is. That’s somewhat 
intentional — the default presentation of an arbitrary Swift value/object is 
defined by the IDE, not by an API in Swift. I think my terminology is a bit 
confused here, and I’ll try to address that in a revision of the proposal. Let 
me try to clarify this a bit:

The fundamental design of playgrounds is that the compiler will insert calls to 
a logging function which is effectively required to take an `Any`. So therefore 
every instance of every type must be loggable by the playground logger. The 
PlaygroundLogger framework in swift-xcode-playground-support 
 implements this by 
generating either structured log entries using `Mirror` or specialized, opaque 
(aka IDERepr) log entries. PlaygroundLogger will generate a structured log 
entry for most instances, but for instances of special types it knows about 
(e.g. String, Int, NSColor, UIView, etc.) it will generate an opaque log entry 
which an IDE can then consume and display as is appropriate.

The CustomPlaygroundRepresentable API I’ve proposed does exactly one thing: it 
allows instances of conforming types to provide an optional stand-in to be used 
by the playground logger. So PlaygroundLogger would handle the following cases 
thusly:

- If a type conforms to CustomPlaygroundRepresentable and returns a 
non-nil value, PlaygroundLogger will generate the appropriate log entry for the 
returned value
- If a type conforms to CustomPlaygroundRepresentable and returns nil, 
PlaygroundLogger will generate the appropriate log entry for `self`
- If `self` is one of the types (or a subclass of one of the 
types) for which PlaygroundLogger generates an opaque entry, PlaygroundLogger 
will generate an opaque log entry
- Otherwise, PlaygroundLogger will generate a structured log 
entry

This process if potentially recursive (likely up to an implementation-defined 
limit): if `Foo: CustomPlaygroundRepresentable` and `Bar: 
CustomPlaygroundRepresentable`, and a `Foo` instance returns an instance of 
`Bar` from `playgroundRepresentation`, then the playground logger should 
effectively log `self.playgroundRepresentation.playgroundRepresentation`.

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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Connor Wakamo via swift-evolution


> On Jan 10, 2018, at 1:58 AM, Ian Partridge  wrote:
> 
> On 9 January 2018 at 23:19, Connor Wakamo via swift-evolution
>  wrote:
>> To that end, I am proposing the following:
>> 
>> - 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 }
>> }
> 
> I was always surprised that "Playground" was a word/concept that the
> Standard Library used, as playgrounds are an Xcode feature and iOS app
> which are not part of the Swift open source project.

Agreed — which is why this proposal moves it into the playground-specific 
PlaygroundSupport library instead of leaving it in the standard library.

> I think it might be better if names for these could be found which
> reflect the functionality they provide, in a non "playground" specific
> way. After all, AFAIK it would be possible for non-"playground" uses
> of CustomPlaygroundRepresentable.

As mentioned in another email, I’m open to naming suggestions. That being said, 
in the same way that there’s `CustomStringConvertible` and 
`CustomDebugStringConvertible`, if we come up with a generic name for this, I 
think I’d still probably want a playground-specific version of it that lives in 
the PlaygroundSupport library so that code can customize its behavior to be 
appropriate for different environments/audiences.

Connor

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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Connor Wakamo via swift-evolution


> On Jan 9, 2018, at 10:02 PM, Chris Lattner  wrote:
> 
> On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
> > wrote:
>> Good afternoon,
> 
> Hi Connor,
> 
> Huge +1 for this proposal, I’m thrilled you’re cleaning this up.  Couple of 
> detail questions:
> 
>>  
>> 
>> 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:
>> 
> 
> 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?

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.

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.)

> 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.  :-)

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.

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 swift-xcode-playground-support 
) 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`.

One possibility would be to change the API so that it returns an enum. Imagine:

enum PlaygroundLoggingBehavior {
/// Asks the playground logger to generate the standard logging 
for `self`.
case standard

/// Asks the playground logger to generate logging for the 
given `Any` instead of `self`.
case custom(Any)
}

protocol CustomPlaygroundLoggable {
/// Returns the `PlaygroundLoggingBehavior` to use for `self`.
var playgroundLoggingBehavior: PlaygroundLoggingBehavior { get }
}

(To Saagar’s point in another email — you could even add a `case none` to 
PlaygroundLoggingBehavior to inhibit logging of a particular instance.)

`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.

>> /// 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 {
> 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?
> 
> The only prior art for the word “Representable” in the standard library is 
> RawRepresentable, which is quite a different concept.
> 
>>   /// Returns the custom playground representation for this instance, or nil 
>> if
>>   /// the default representation should 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Saagar Jha via swift-evolution
Well, in my experience performance issues tend to come not from trying to 
display a single object, but when you have an aggregation of many objects. For 
example, displaying one Int is pretty lightweight, as is an [Int] with a 
handful of elements, but displaying an [Int] with million elements is not (this 
is assuming that collections will run the playgroundRepresentation on their 
individual elements as they do currently). I don’t think the current proposal 
can solve this issue as it’s pitched currently. (For those curious, this 
doesn’t have a good solution today, either: the best “solution” I’ve been able 
to come up with is to move performance-sensitive out into a Playground’s 
Sources folder, which isn’t displayed.)

Fundamentally, I don’t think it’s clear what the “default” value is supposed to 
be: we already have three different interpretations of what it could do: do 
literally nothing (i.e. display an empty representation), use a superclass’s 
representation, or use a structural representation based on whether the type is 
an enum, struct, class, etc. I think we need to clear up what the default 
actually means (and if we even need it at all) before we can proceed.

Saagar Jha

> On Jan 10, 2018, at 10:02, Chris Lattner  wrote:
> 
>> On Jan 9, 2018, at 11:30 PM, Saagar Jha  wrote:
>>> 
>>> 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.  :-)
>> 
>> I believe the rationale behind this was to provide a way to “opt-out” of a 
>> customized representation, although now that I think about it, what exactly 
>> does the default mean? In particular, what happens in this case?
> 
> If you want a type to display as nothing (e.g. to avoid the perf impact of 
> formatting it) just make the playground representation be an empty string or 
> something.
> 
> -Chris
> 
> 

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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Chris Lattner via swift-evolution

> On Jan 10, 2018, at 10:10 AM, Riley Testut  wrote:
> 
> On Jan 9, 2018, at 10:02 PM, Chris Lattner via swift-evolution 
> > wrote:
> 
>> 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?
> 
> I assumed it could be used if a type’s playground representation was 
> variable. For instance:
> 
> enum MyUnion
> {
> case string(String)
> case image(UIImage)
> case none
> }
> 
> In its implementation of CustomPlaygroundRepresentable, it could return a 
> string if case string, an image if case image, or return nil if case none to 
> just do whatever is the default for enum values. 
> 
> Admittedly the above is a very contrived example, but I do think it is 
> important to allow types to opt-out.

You should just be able to return ‘self' in that case?

-Chris


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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Riley Testut via swift-evolution
> On Jan 9, 2018, at 10:02 PM, Chris Lattner via swift-evolution 
>  wrote:


> 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?

I assumed it could be used if a type’s playground representation was variable. 
For instance:

enum MyUnion
{
case string(String)
case image(UIImage)
case none
}

In its implementation of CustomPlaygroundRepresentable, it could return a 
string if case string, an image if case image, or return nil if case none to 
just do whatever is the default for enum values. 

Admittedly the above is a very contrived example, but I do think it is 
important to allow types to opt-out.

> On Jan 9, 2018, at 10:02 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
>>  wrote:
>> Good afternoon,
> 
> Hi Connor,
> 
> Huge +1 for this proposal, I’m thrilled you’re cleaning this up.  Couple of 
> detail questions:
> 
>> 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:
>> 
> 
> 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?
> 
> 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.  :-)
> 
> 
>> /// 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 {
> 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?
> 
> The only prior art for the word “Representable” in the standard library is 
> RawRepresentable, which is quite a different concept.
> 
>>   /// 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 }
> Again to align with CustomStringConvertible which has a ‘description’ member, 
> it might make sense to name this member “playgroundDescription”.
> 
> Thank you again for pushing this forward, this will be much cleaner!
> 
> -Chris
> 
> 
> ___
> swift-evolution mailing list
> 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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Chris Lattner via swift-evolution
> On Jan 9, 2018, at 11:30 PM, Saagar Jha  wrote:
>> 
>> 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.  :-)
> 
> I believe the rationale behind this was to provide a way to “opt-out” of a 
> customized representation, although now that I think about it, what exactly 
> does the default mean? In particular, what happens in this case?

If you want a type to display as nothing (e.g. to avoid the perf impact of 
formatting it) just make the playground representation be an empty string or 
something.

-Chris


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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-10 Thread Ian Partridge via swift-evolution
On 9 January 2018 at 23:19, Connor Wakamo via swift-evolution
 wrote:
> To that end, I am proposing the following:
>
> - 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 }
> }

I was always surprised that "Playground" was a word/concept that the
Standard Library used, as playgrounds are an Xcode feature and iOS app
which are not part of the Swift open source project.

I think it might be better if names for these could be found which
reflect the functionality they provide, in a non "playground" specific
way. After all, AFAIK it would be possible for non-"playground" uses
of CustomPlaygroundRepresentable.

-- 
Ian Partridge
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Saagar Jha via swift-evolution

Saagar Jha

> On Jan 9, 2018, at 22:02, Chris Lattner via swift-evolution 
>  wrote:
> 
> On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
> > wrote:
>> Good afternoon,
> 
> Hi Connor,
> 
> Huge +1 for this proposal, I’m thrilled you’re cleaning this up.  Couple of 
> detail questions:
> 
>>  
>> 
>> 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:
>> 
> 
> 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?
> 
> 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.  :-)

I believe the rationale behind this was to provide a way to “opt-out” of a 
customized representation, although now that I think about it, what exactly 
does the default mean? In particular, what happens in this case?

// I’m not sure how this will be implemented: possibly UIView won’t conform to 
CustomPlaygroundRepresentable and the first class inheriting from it will do 
this?
// Either way, it shouldn’t really affect my example since this will just mean 
that FooView will implement it instead
class UIView: CustomPlaygroundRepresentable {
var playgroundRepresentation: Any? {
return self // I assume this is done somewhere in the bowels of 
PlaygroundSupport or whatever
}
}

class FooView: UIView {
override var playgroundRepresentation: Any? {
return “foo”
}
}

class BarView: FooView {
override var playgroundRepresentation: Any? {
return nil
}
}

In this case, what’s the default? UIView’s implementation, or that of the 
immediate parent (FooView’s)?

> 
> 
>> /// 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 {
> 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?
> 
> The only prior art for the word “Representable” in the standard library is 
> RawRepresentable, which is quite a different concept.
> 
>>   /// 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 }
> Again to align with CustomStringConvertible which has a ‘description’ member, 
> it might make sense to name this member “playgroundDescription”.
> 
> Thank you again for pushing this forward, this will be much cleaner!
> 
> -Chris
> 
> 
> ___
> swift-evolution mailing list
> 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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Chris Lattner via swift-evolution
On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
 wrote:
> Good afternoon,

Hi Connor,

Huge +1 for this proposal, I’m thrilled you’re cleaning this up.  Couple of 
detail questions:

>  
> 
> 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:
> 

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?

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. 
 :-)


> /// 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 {
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?

The only prior art for the word “Representable” in the standard library is 
RawRepresentable, which is quite a different concept.

>   /// 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 }
Again to align with CustomStringConvertible which has a ‘description’ member, 
it might make sense to name this member “playgroundDescription”.

Thank you again for pushing this forward, this will be much cleaner!

-Chris


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


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Connor Wakamo via swift-evolution


> On Jan 9, 2018, at 4:21 PM, Ben Rimmington  wrote:
> 
> Something like this was attempted (and reverted) for Swift 3:
> 
> 
> 
> 
> 
> 
> 
> Is it now possible to `import PlaygroundSupport` outside of a playground?

No, it is not. This is a known limitation of the proposal that is acknowledged 
in the full text of the proposal.

For the corelibs case (and for libraries provided by the OS), it’s expected 
that the PlaygroundLogger library be updated to support generating rich log 
data for new types.

For third-party modules there’s not a great solution, though since playgrounds 
have fairly limited access to third-party modules and because usage of 
CustomPlaygroundQuickLookable outside of playgrounds is low (as determined by 
searching GitHub and the source compatibility suite), the proposal asserts that 
this is a reasonable trade-off for removing something this domain-specific from 
the standard library.

Since the new protocol doesn’t itself use any custom types, a workaround for 
this limitation is possible:

// MyFramework.swift
public struct MyStruct {
var playgroundRepresentation: Any? { … }
}

// PlaygroundAuxiliarySource.swift
import MyFramework
import PlaygroundSupport

extension MyStruct: CustomPlaygroundRepresentable {}

The proposal intentionally chose to place this in PlaygroundSupport instead of 
the standard library because it should be possible in a future Swift release to 
move this protocol from PlaygroundSupport to the standard library (because 
PlaygroundSupport doesn’t have any ABI concerns at this time), whereas it 
wouldn’t be possible to go in the reverse direction. (And if we determine that 
this protocol should live in the standard library during the course of the 
review process, I’d still want to proceed otherwise as planned — add the new 
protocol, deprecate-then-remove the old protocol/enum, and provide a shim 
library for playgrounds only.)

Connor

> 
> -- Ben
> 
>> On 9 Jan 2018, at 23:19, Connor Wakamo 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

___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Ben Rimmington via swift-evolution
Something like this was attempted (and reverted) for Swift 3:







Is it now possible to `import PlaygroundSupport` outside of a playground?

-- Ben

> On 9 Jan 2018, at 23:19, Connor Wakamo 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Connor Wakamo via swift-evolution
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  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 
>> > 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- 
>> 
>> Authors: Connor Wakamo 
>> Review Manager: TBD
>> Status: Awaiting implementation
>>  
>> 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. 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

2018-01-09 Thread Ben Cohen via swift-evolution
Big +1 to this. Getting these types out of the standard library and into a more 
suitable domain-specific framework, prior to declaring ABI Stability, will give 
us flexibility to evolve them appropriately over time.

> On Jan 9, 2018, at 3:19 PM, Connor Wakamo via swift-evolution 
>  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- 
> 
> Authors: Connor Wakamo 
> Review Manager: TBD
> Status: Awaiting implementation
>  
> 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 
>  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