[swift-evolution] [Proposal] Foundation Swift Archival & Serialization
Itai Ferber
iferber at apple.com
Fri Mar 17 17:32:47 CDT 2017
On 17 Mar 2017, at 13:36, Joe Groff wrote:
> > On Mar 17, 2017, at 12:49 PM, Itai Ferber <iferber at apple.com> wrote:
>>
>> On 17 Mar 2017, at 12:18, Michael Gottesman wrote:
>>
>>
>> On Mar 16, 2017, at 10:23 AM, Joe Groff via swift-evolution
>> <swift-evolution at swift.org> wrote:
>>
>> On Mar 16, 2017, at 10:21 AM, Itai Ferber <iferber at apple.com> wrote:
>>
>> On 15 Mar 2017, at 19:12, Joe Groff wrote:
>>
>>
>> On Mar 15, 2017, at 6:46 PM, Itai Ferber <iferber at apple.com> wrote:
>>
>> Thanks Joe, and thanks for passing this along!
>>
>> To those who are curious, we use abstract base classes for a
>> cascading list of reasons:
>>
>> • We need to be able to represent keyed encoding and decoding
>> containers as abstract types which are generic on a key type
>> • There are two ways to support abstraction in this way: protocol &
>> type constraints, and generic types
>> • Since Swift protocols are not generic, we unfortunately cannot
>> write protocol KeyedEncodingContainer<Key : CodingKey> { ... }, which
>> is the "ideal" version of what we're trying to represent
>> • Let's try this with a protocol first (simplified here):
>>
>> protocol Container {
>> associatedtype Key : CodingKey
>> }
>>
>> func container<Key : CodingKey, Cont : Container>(_ type: Key.Type)
>> -> Cont where Cont.Key == Key {
>> // return something
>> }
>>
>> This looks promising so far — let's try to make it concrete:
>>
>> struct ConcreteContainer<K : CodingKey> : Container {
>> typealias Key = K
>> }
>>
>> func container<Key : CodingKey, Cont : Container>(_ type: Key.Type)
>> -> Cont where Cont.Key == Key {
>> return ConcreteContainer<Key>() // error: Cannot convert return
>> expression of type 'ConcreteContainer<Key>' to return type 'Cont'
>> }
>>
>> Joe or anyone from the Swift team can describe this better, but this
>> is my poor-man's explanation of why this happens. Swift's type
>> constraints are "directional" in a sense. You can constrain a type
>> going into a function, but not out of a function. There is no type I
>> could return from inside of container() which would satisfy this
>> constraint, because the constraint can only be satisfied by turning
>> Cont into a concrete type from the outside.
>>
>> Okay, well let's try this:
>>
>> func container... {
>> return ConcreteContainer<Key>() as! Cont
>> }
>>
>> This compiles fine! Hmm, let's try to use it:
>>
>> container(Int.self) // error: Generic parameter 'Cont' could not be
>> inferred
>>
>> The type constraint can only be fulfilled from the outside, not the
>> inside. The function call itself has no context for the concrete type
>> that this would return, so this is a no-go.
>>
>> • If we can't do it with type constraints in this way, is it
>> possible with generic types? Yep! Generic types satisfy this without
>> a problem. However, since we don't have generic protocols, we have to
>> use a generic abstract base class to represent the same concept —
>> an abstract container generic on the type of key which dynamically
>> dispatches to the "real" subclassed type
>>
>> Hopes that gives some simplified insight into the nature of this
>> decision.
>>
>> I see. Protocols with associated types serve the same purpose as
>> generic interfaces in other languages, but we don't have the
>> first-class support for protocol types with associated type
>> constraints (a value of type `Container where Key == K`). That's
>> something we'd like to eventually support. In other places in the
>> standard library, we wrtie the type-erased container by hand, which
>> is why we have `AnySequence`, `AnyCollection`, and `AnyHashable`. You
>> could probably do something similar here; that would be a bit awkward
>> for implementers, but might be easier to migrate forward to where we
>> eventually want to be with the language.
>>
>> -Joe
>>
>> Yep, that’s a good way to describe it.
>> We could potentially do that as well, but adding another type like
>> AnyHashable or AnyCollection felt like a much more sweeping change,
>> considering that those require some special compiler magic themselves
>> (and we’d like to do as little of that as we can).
>>
>> AnyCollection doesn't have any special compiler magic. AnyHashable's
>> only magic is that it has implicit conversions, but that would become
>> normal behavior once it can be replaced by a plain Hashable
>> existential type.
>>
>> Hey Itai. I am not sure if I missed this. But did you follow up with
>> why you didn't want to use AnyCollection/AnyHashable? The thread got
>> really long pretty fast.
>>
>> I responded to this in a different part of the thread very recently.
>> Can you elaborate on how a type like AnyCollection/AnyHashable would
>> help here? More important than the type erasure is the type being
>> generic on the key type, and this must be specified. How would this
>> be possible
>>
>>
>
> You can implement an AnyContainer<Key> type that conforms to the
> Container protocol, using an abstract base class that erases the type,
> and a private subclass that forwards the interface to a contained
> value.
> https://www.bignerdranch.com/blog/breaking-down-type-erasure-in-swift/
> <https://www.bignerdranch.com/blog/breaking-down-type-erasure-in-swift/>
> runs the technique down fairly well. I don't see any obvious reason we
> couldn't do that here. The tradeoff I see is whether the inconvenience
> of manually wrapping conforming types in AnyContainer outweighs
> the constraint that container implementations must be subclasses
> instead of having the full freedom of being value types or subclasses
> in a different class hierarchy conforming to a protocol.
>
> -Joe
Thanks for the clarification — I talked to Tony about this briefly and
the idea gelled a bit more.
I’ll investigate this; you’re right, this seems doable.
Thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170317/28c996fb/attachment.html>
More information about the swift-evolution
mailing list