> 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

Reply via email to