> On Dec 30, 2015, at 10:27 AM, Matthew Johnson <matt...@anandabits.com> wrote: > > >> On Dec 30, 2015, at 10:06 AM, plx via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> Thanks for writing this up. > > Thanks for responding with comments. > >> >> Some quick points. >> >> Firstly, I think it is best if the `init(_ forwardeeReturnValue: >> Forwardee)`-style initializer be replaced by something with a >> distinctly-named argument, e.g. `init(forwardeeReturnValue value: >> Forwardee)`. >> >> For use with actual wrapper types the “init(_ wrappedValue: Wrapped)`-style >> init is too valuable to “claim” for this purpose (in particular b/c we may >> want to “adjust" the forwarded result); it’s IMHO better if we use a >> distinct `init` for the forwardee-return-value scenario so we know where the >> value is coming from. > > Did you look at the approach Brent suggested yesterday? I’m going to update > the proposal using something similar to that. We won’t be claiming any init > at all. It will be slightly less concise in the common case but will add > clarity, expressiveness, and resolve problems related to forwarding to more > than one member of the same type.
I did not but will make sure to read it. > >> >> Secondly, I would prefer partial-forwarding be given more consideration, b/c >> it seems somewhat common for me in practice at this time. > > If somebody from the core team was enthusiastic about including partial > forwarding in the initial proposal rather than as an enhancement that would > certainly motivate me to reconsider. > > As I stated earlier and in the proposal, one reason I left it out is that > partial forwarding introduces similar concerns that arise with subclassing. > Should a protocol or a type designed to be a forwardee be able to include > annotations indicating that some members cannot be “overriden” by a > forwarder? I haven’t had time to fully consider whether that is a good idea > or not and if it is, what it would look like, how it should work, etc. I am > reluctant to introduce partial forwarding without really thinking this > through. > >> >> EG: I would do the following somewhat frequently: >> >> struct FooIdentifier: Equatable, Comparable, Hashable >> >> class Foo { >> let identifier: FooIdentifier >> let name: String >> >> forward Hashable to identifier >> } >> >> func ==(lhs: Foo, rhs: Foo) -> Bool { >> return lhs.identifier == rhs.identifier && lhs.name == rhs.name >> } >> > > Thanks for providing an example! It looks like you would have two different > instances representing the same entity, possibly one serving as an edit > buffer. Is that why they might have the same identifier but different names? > This is suffering from the “short examples will necessarily feel contrived, long examples are too long to be polite” problem. Sometimes it’s just from laziness — a good composite `hashValue` can be hard to write, so why not stick with a known-good `hashValue` implementation? — and often makes sense in context (if you know that same-ID, logically-different objects will be rare enough to have negligible overall impact). I totally agree though I’m getting essentially nothing from forwarding here. Similar scenarios can show up somewhat *artificially* in the context of generic code. Here’s a somewhat-contrived example: Suppose you want to write a generic function that can look an “old” array and a “new” array and infer an “edit sequence” that can be applied to transform the “old” one into the “new” one, with an added complication: some values in the “new” one are *revisions* of values from the old one (and thus !=, but still “representing the same thing”). This could be implemented a lot of different ways; one of them might look like this: protocol RecordIdentifierType : Equatable, Comparable, Hashable {} // etc protocol IdentifiableRecordType : Equatable, Hashable { typealias Identifier: RecordIdentifierType typealias Data: Equatable // weakest guarantee we need for what we plan to use this for // deliberately-clunky names to avoid accidental collisions: var recordIdentifier: Identifier { get } var recordData: Data { get } } func inferredEditOperations<R:IdentifiableRecordType>( forPreviousRecords previousRecords: [R], currentRecords: [R]) -> ArrayEditOperation { // exercise for reader } …wherein 99% of the time a typical concrete conformance would just return `self` as `recordData` and some appropriate property as `recordIdentifier`, but it’d still be handy to have an “adaptor" type laying around like this: struct IdentifiableRecordAdaptor<I:RecordIdentifierType,D:Equatable> : IdentifiableRecordType { typealias Identifier = I typealias Data = D let recordIdentifier: I let recordData: D forwarding Hashable to RecordIdentifier } …to support broader use of the generic algorithm in certain cases. Note that this is still quite contrived — and it's still just `Equatable`/`Hashable` — but I think you can see how the scenario here could generalize in other contexts. But at the same time, perhaps partial-forwarding is actually more of a niche use here than I thought? > >> …even though I agree that full-forwarding would the most-common scenario. >> >> I have a few other similar cases involving non-standard-library types but >> they all fit the same basic pattern as above for `Hashable`. >> >> Finally, I’m actually at a bit of a loss for too many uses for the generic >> forwarding mechanism; if it was added I’d use it to streamline some wrapper >> types, but beyond that I’m not seeing all that many places where I’d do much >> more than that with this feature if added. >> >> Any chance at adding a few more-concrete motivating examples for the fancier >> cases? > > Yes, this is needed and I am working on it now. > >> >>> On Dec 29, 2015, at 10:37 AM, Matthew Johnson via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> I have completed a first draft of a proposal to introduce automatic >>> protocol forwarding. I’m looking forward to feedback from everyone! >> >> _______________________________________________ >> 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