> On Apr 12, 2017, at 11:44 AM, Russ Bishop via swift-evolution
> <[email protected]> wrote:
>
> * String and Int keys being optional, giving a CodingKey the opportunity to
> return nil for both at runtime.
This was true in the first public draft, but I believe in this version
`stringValue` is no longer Optional.
> * Encoder has three functions, but only one may ever be called. This API is
> the opposite of "pit of success".
Personally, I'm worried about that too. But I had a lot of trouble coming up
with an alternative that didn't violate a more important goal, like "being able
to throw errors" or "being compatible with classes".
Last-ditch suggestion: Change a bunch of names so that, for instance, `Encoder`
is instead `EncodingContainerizer`. (That's a terrible name, but "Factory"
gives me the hives.) That way, the name of the type gives you a hint that
you're supposed to use it to make a container. You might even rename the
methods to e.g. `useContainer(keyedBy:)`, which sound a little more stateful
and mutually-exclusive.
func encode(to encoder: EncodingContainerizer) throws {
var container = encoder.useContainer(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(birthDate, forKey: .birthDate)
}
> I don't understand why KeyedEncodingContainer needs all those overloads;
> automatic conformance to Encodable should be provided for the stdlib types in
> those overloads so why would they be necessary?
I argued about this pretty vigorously. They want to avoid the overhead of
building an encoder and single-value container and then making several generic
calls to encode the value into the container. Personally, I think this is
premature optimization of the highest order—particularly since building an
encoder and single-value container are often no-ops—but this is the design they
chose, and I don't think it's worth rejecting for that alone.
> KeyedEncodingContainer.encodeWeak seems like it should be a protocol
> refinement so you can check for the capability (or potentially know at
> compile time).
This probably ends up duplicating not only `KeyedEncodingContainerProtocol`,
but also `UnkeyedEncodingContainer`, `Encoder`, and `Encodable`. Doable, yes.
Worth it, especially when `encodeWeak` has a pretty sensible fallback behavior?
Eh.
> (One minor bit of bike shedding: decode/decodeIfPresent could instead be
> decode(required:) and decode(optional:)).
I don't think `required:` and `optional:` are really helpful. The name here is
kind of like `addingWithOverflow(_:_:)`—you really want it to be `adding(x, y,
.withOverflow)`, but it's not worth creating a dummy enum just to make a method
read properly. Similarly, you'd like `decode(Int.self, .ifPresent)`, but the
dummy's not worth the better readability.
I'm not sure why we don't do this, though:
// Just showing Unkeyed for simplicity
func decode<T: Decodable>(_ type: T.Type) throws -> T
func decode<T: Decodable>(_ type: Optional<T>.Type) throws -> T?
let alwaysInt = try container.decode(Int.self)
let maybeInt = try container.decode(Int?.self)
> I really strongly dislike mixing up the Unkeyed and Keyed concepts. A type
> should need to explicitly opt-in to supporting unkeyed and that should be
> enforced at compile time. Unkeyed encoding is a potential versioning
> nightmare and should be handled with care.
I think they've done a reasonable job of putting unkeyed coding in a sharps
drawer by making you specifically ask for it and giving it an ugly name.
> C#'s serialization attributes are a better and more comprehensive solution
> but we don't have custom attributes in Swift and property behaviors were
> deferred. This problem is too important to leave to the future though. If we
> did ever add custom attributes or if property behaviors get implemented then
> this design could adopt them incrementally without breaking compatibility
> (e.g. a serialization transformer behavior that turns a non-Encodable
> property into an Encodable one, or a behavior that ignores a property for
> serialization purposes).
On the contrary, I think we *can* safely leave this to the future. If a future
version of Swift and Foundation added:
@uncoded var foo: Bar
That would be a completely additive change. Until then, there's an irritating
but serviceable solution available—write your own CodingKeys enum and let code
generation write the `Codable` conformances based on it.
--
Brent Royal-Gordon
Architechies
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution