Sent from my iPhone

> On Mar 19, 2017, at 10:47 AM, Tony Parker <anthony.par...@apple.com> wrote:
> 
> Hi Matthew, Brent,
> 
> I see why you are asking for this Context parameter, but putting it into the 
> basic Codable protocol introduces too much conceptual overhead. There are too 
> many benefits to keeping adoption to just one protocol, including 
> discoverability, ease of use, reducing the need for overloads on protocols 
> elsewhere, and more. Supporting this one use case does not outweigh those 
> benefits, especially considering I expect that most library code would not 
> use it (as you say: it would be weird to pass this context between modules).
> 
> Can you figure out a way to get the context info passed through the 
> encoder/decoder instead? It would make more sense as something optionally 
> retrieved from the encoder/decoder that was set at the top level.

Hi Tony.  I can see the argument that the this is a feature that should be 
relatively rarely used and thus should have as simple a design as possible.

If you feel like the impact of threading a typed context on the API surface 
area is too heavy you could just add a `var context: Any? { get }` requirement 
to Encoder and Decoder.  The expectation is that encoders and decoders would 
accept a context in the top level call and make it available to all Codable 
types.  This would solve the problem with minimal API impact at the cost of the 
ability to statically verify that all types receive the context they need to 
encode / decode correctly.

I much prefer the static safety but having a solution is better than not having 
one.  :)

> 
> - Tony
> 
>>> On Mar 17, 2017, at 5:56 PM, Matthew Johnson via swift-evolution 
>>> <swift-evolution@swift.org> wrote:
>>> 
>>> 
>>>> On Mar 17, 2017, at 6:15 PM, Brent Royal-Gordon <br...@architechies.com> 
>>>> wrote:
>>>> 
>>>>> On Mar 17, 2017, at 3:35 PM, Matthew Johnson <matt...@anandabits.com> 
>>>>> wrote:
>>>>> 
>>>>> In all seriousness, I see the design as very slightly weak, in that it 
>>>>> makes it easy to forget to pass a context through, but quite acceptable. 
>>>> 
>>>> Easy for who?  I was not requiring Codable types to thread it through at 
>>>> all.  The context was fully managed by the Encoder / Decoder type.  The 
>>>> only place Codable types work with the context is as an argument they 
>>>> receive.  They never pass it when encoding or decoding anything.  The 
>>>> Encoder / Decoder would need to store the context internally and when call 
>>>> is made to encode / decode a ContextAwareCodable it would pass the result 
>>>> of a dynamic cast to ContextAwareCodable.Context as the context.
>>> 
>>> Oh, I see. Sorry, I missed that when I was looking at your design.
>>> 
>>> In practice, in my design, you would only need to manually pass a context 
>>> to `encode(_:forKey:with:)` if the context was of a different type than 
>>> `self`’s. 
>> 
>> Oh, I see.  I missed that part of your design.  I really like it with the 
>> shorthands.  I’m fully on board with this being the right way to handle 
>> contexts now.  I think Context should be in the basic Codable protocol.  
>> That leaves the question of what to do with NSKeyedArchiver and 
>> NSKeyedUnarchiver.  I’m not sure what the answer is for those but it would 
>> be unfortunate to see the design compromised solely because of a requirement 
>> to interoperate with them.
>> 
>>> This would probably happen at module or subsystem boundaries. Imagine, for 
>>> instance, that your FooKit module (for interacting with the foo.io web 
>>> service) needs to encode a GeoKit.Location instance, but both FooKit and 
>>> GeoKit need information from a context to encode themselves properly, and 
>>> they use different context types. When FooKit encoded a GeoKit.Location, it 
>>> could construct and pass a GeoKit context.
>>> 
>>> I believe that in your design, unless the FooKit context was a subtype of 
>>> the GeoKit context, you wouldn't be able to get GeoKit.Location to do the 
>>> right thing.
>> 
>> Right.  It was assuming only one context would be needed for an entire 
>> encoding / decoding process.  I don’t know of use cases where one module 
>> could meaningfully provide a context to another module unless they were very 
>> closely related (i.e. built as parts of the same system) but maybe they do 
>> exist.  Your design is able to accommodate this very well.
>> 
>> I made some compromises to try and diverge from the current proposal as 
>> little as possible while still solving the primary use cases I’m aware of.  
>> Now that I understand your design I think it has enough advantages that we 
>> should go in that direction.  And we certainly should not go in the 
>> direction of something that requires Any.
>> 
>>> 
>>> If that weren't the case—if you were encoding a type with a matching 
>>> context, or with a `Void` context—you could use the two convenience 
>>> methods, which would handle the context argument for you. So threading 
>>> contexts would only be necessary in a relatively rare case.
>> 
>> Yep, that’s very elegant!
>> 
>>> 
>>> -- 
>>> Brent Royal-Gordon
>>> Architechies
>>> 
>> 
>> _______________________________________________
>> 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

Reply via email to