[swift-evolution] Possible issue with SE-0166 Swift Archival & Serialization implementation

Gwendal Roué gwendal.roue at gmail.com
Thu Jun 8 12:20:29 CDT 2017


> On Jun 8, 2017, at 9:45 AM, Itai Ferber <iferber at apple.com <mailto:iferber at apple.com>> wrote:
> 
> Hi Gwendal,
> 
>> On Jun 8, 2017, at 8:27 AM, Gwendal Roué via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>>> 
>>> Le 8 juin 2017 à 16:51, James Froggatt via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
>>> 
>>> I've just been trying out the new Coding protocol, and was rather surprised when trying to implement the `encode(to encoder: Encoder)` method.
>>> 
>>> The Swift evolution proposal provides the following example code:
>>> 
>>>   public func encode(to encoder: Encoder) throws {
>>>       // Generic keyed encoder gives type-safe key access: cannot encode with keys of the wrong type.
>>>       let container = encoder.container(keyedBy: CodingKeys.self)
>>> 
>>>       // The encoder is generic on the key -- free key autocompletion here.
>>>       try container.encode(latitude, forKey: .latitude)
>>>       try container.encode(longitude, forKey: .longitude)
>>>   }
>>> 
>>> 
>>> Here, container is stored as a `let` value, and uses reference semantics, while the proposal also clearly lists these `encode` methods as mutating. With the current implementation of the proposal, the container must be stored as a `var`, which leads to code like the following:
>>> 
>>>   var container = encoder.singleValueContainer()
>>>   try container.encode(data)
>> 
>> Yes, practically speaking and with latest Swift 4, the container needs to be declared as `var`.
>> 
>> I admit it's weird, and feels unnatural:
>> 
>>   public func encode(to encoder: Encoder) throws {
>>       // A mutated value that nobody consumes: so weird.
>>       var container = encoder.container(keyedBy: CodingKeys.self)
>>       try container.encode(latitude, forKey: .latitude)
>>       try container.encode(longitude, forKey: .longitude)
>>   }
> Why? It’s perfectly reasonable for the container to maintain some internal state as it’s encoding. It shouldn’t have to sacrifice value semantics for that.

No big trouble, Itai: just that a value type is usually mutated before being used elsewhere.

Take this code snippet for example:

	var a = [1]
	a.append(2)
	// if a is not used any longer, something is wrong, don't you agree?

And now this other one:

	var x = SomeValueType()
	x.append(2)
	// why would it be different for x?

One of the *possible* interpretations of value types is that they are (or look like, if you prefer) purely local, and without side effect.

I know that values can hold references and vice-versa, and that the exact distinction between value and reference types is thin, even generally in the hand of the library developer: one can expose a reference type that behaves like a value type, and one can write a value type that obviously hides some references (like the containers above).

That's all. No big deal, really.
Gwendal

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170608/ca9a1c9e/attachment.html>


More information about the swift-evolution mailing list