> On Dec 30, 2015, at 10:27 AM, Matthew Johnson <[email protected]> wrote:
>
>
>> On Dec 30, 2015, at 10:06 AM, plx via swift-evolution
>> <[email protected]> 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
>>> <[email protected]> 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
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution