Mark protocol methods with their protocol

I don't think "override" is a good idea. It's not overriding.

Protocol is not Class.

I think you make a good point. It seems like people have generally written
about "overriding" default implementations, but that might not be the best
term and it may be a little confusing. Is there a "more correct" word for
this scenario?

Xiaodi Wu via swift-evolution <swift-evolution@swift.org>于2016年9月20日

···

On Mon, Sep 19, 2016 at 7:15 PM, Boris Wang <kona.ming@gmail.com> wrote:

周二08:04写道:

I definitely think Vladimir's suggestion is a great starting point, IMO.

However, I think it could be improved in one key respect where previous
proposals using `override` are superior. Namely, the proposed `implement`
keyword adds no additional safety when a type implements a protocol
requirement that doesn't have a default implementation. This is because, if
there's a "near-miss" typo in the function signature, an error is already
generated at compile time because the type doesn't conform to the stated
protocol. Currently, the error is very unhelpful, but IMO that's a
straight-up bug; improving the diagnostics for that error can be done
without evolution.

On the other hand, if we require `implement`, the simplest use case of
conforming a type to a protocol with no default implementations would take
more effort but provide no benefit to justify that additional effort.
Moreover (I think a core team member has expressed this more elegantly in
the past), there's the philosophical point that POP represents the
theoretical process by which we discover and express our discovery that
certain types happen to share common semantic characteristics. In that
conception of POP, it would be backwards to declare a certain member as
fulfilling certain protocol requirements.

So, if such a source breaking change were to be in scope for Swift, I
would suggest modifying Vladimir's proposal to use `override` instead and
requiring the keyword only when a default implementation is being
overridden. To accommodate retroactive conformance, we could either propose
that `extension Foo : Bar` is automatically understood to contain members
that override default implementations (as Vladimir has essentially
suggested), or stipulate that we must write `extension Foo : override Bar`.
This has the advantage of not introducing an additional keyword and avoids
the seemingly reduplicative spelling `extension Foo : implement Bar` (for
what else would an `extension Foo : Bar` reasonably do but implement the
requirements of Bar?).

On Mon, Sep 19, 2016 at 3:10 PM, Goffredo Marocchi via swift-evolution < >> swift-evolution@swift.org> wrote:

If Swift 4 will make it impossible to tackle this again, I do not think
discussing this can be avoided for Swift 3.1... I am afraid we are rushing
into Swift 4 a bit too quickly, but perhaps it is just silly old me :).

Sent from my iPhone

On 19 Sep 2016, at 19:18, Charles Srstka via swift-evolution < >>> swift-evolution@swift.org> wrote:

On Sep 19, 2016, at 12:10 PM, Vladimir.S via swift-evolution < >>> swift-evolution@swift.org> wrote:

On 17.09.2016 6:32, Xiaodi Wu via swift-evolution wrote:

Let me give a concrete example of how retroactively modeling is used.

Karl is suggesting interesting but complex and IMO too much
code-breaking idea that I don't believe can be implemented at all in a
reasonable amount of time to be a part of Swift as soon as possible, to
address the discussed issue with protocols.

I wonder what objections could be made on the solution proposed below,
which should solve a major(IMO) number of issues with protocol conformance
and introduce only 1 keyword. Such solution will make Swift better as
Protocol-Oriented language and later we can even improve it, but it can
already solve a big number of issues:

1. As soon as possible we add 'implement' keyword which is required to
mark method/property that was defined in type or extension exactly to
conform to some protocol.

2. The 'implement' required only at a moment of 'direct' conformance,
i.e. when you declare methods/props of the type/extension that explicitly
conformed to protocol.

3. Retrospective conformance will not require this keyword and will work
for now just like it is working today.

4. Later, if this will be possible at all, we can extend this model to
support separate implementation of protocols with same requirements in the
same type, explicit protocol name in implemented methods/props and
improvements for retrospective conformance. For example some variants for
*future* improvements:

4.1 Different implementation for different protocols
class Foo : ProtocolA, ProtocolB {
implement(ProtocolA) func foo() {...}
implement(ProtocolB) func foo() {...}
}
class Foo : ProtocolA, ProtocolB {
implement ProtocolA {
func foo() {...}
}
implement ProtocolB {
func foo() {...}
}
}
etc

4.2 Retrospective conformance: What is the main problem with
retrospective conformance? As I see it now(correct me, if I missing
something), the problem arises in such situation:
* we *expect* that some method(s) in type will play the role of
implementation of protocol's requirements, so we retrospectively conform
that type to the protocol.
* but protocol has default implementation for its requirements
* and type's methods, that we *expect* to play roles for protocol
implementation, has different parameters or slightly different method name
at all.

I.e. when we have this set of code logic:

type T {
func foo()
}

protocol P {
func foo(x: Int)
}

extension P {
func foo(x: Int) {...}
}

extension T : P { // expect foo in T will play role of P.foo
}

I support the opinion that it is not an option to require to explicitly
list conformed methods/props in type extension for retrospective
conformance.
But I do believe we need a way to *express our intention* regarding the
retrospective conformance: do we expect that type already contains
implementation for some protocol's requirements OR we are aware that
protocol can have defaults for some methods and our type does not contains
some implementations.

So, the solution here IMO is some syntax to express that intention.
Right now I think that we can use current syntax "extension T : P" to keep
it working as it now works: "I'm aware of all the names, defaults etc.
Treat this as usually you did". But for example something like "extension
T: implement P {..}" or "extension T: P(implement *) {..}" will say that we
*expect* that all requirements of P protocol should be implemented inside T
type. Or some syntax inside extension to specify the list of methods/props
we expect to be implemented in T. Or "extension T : P(implement foo,
bar(x:y:)) {..}".. Should be discussed.

But again, IMO this could be discussed later, after we'll have
'implement' for most important place - in type definition for method/prop
that we created exactly for the conformed protocol.

I would be completely +1 on this.

Charles

_______________________________________________
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Requiring the ‘implement’ keyword can help us even if no default implementation is involved. Consider:

protocol P {
  func foo() -> [String : Any]
}

struct S : P {
  func foo() -> [String : String] { return [:] }
}

We will get an error here that S does not conform to P. However, this is not the correct error, since S in fact *tries* to conform to P, but it has a mistake in a method signature. This misleads us as to the true nature of the problem, and if S has enough members in it that we fail to spot the existing foo(), we might solve the problem by reimplementing foo(), and leaving the original foo() as dangling dead code. Having an ‘implement’ keyword on the existing foo() function would change the compiler error to let us know that we have an existing foo() that is incorrectly declared.

In addition, ‘implement’ can help us when the declaration in question *is* the default implementation:

protocol P {
  func foo() -> [String : Any]
}

extension P {
  implement func foo() -> [String : String] { return [:] }
}

Here we will get an error with the proposed ‘implement’ keyword, because foo() does not have a signature matching anything in the protocol, whereas without ‘implement’ we would happily and silently generate a useless dangling function that would never be used, and then pass the buck to the concrete type that implements P:

protocol P {
  func foo() -> [String : Any]
}

extension P {
  func foo() -> [String : String] { return [:] } // The error is here:
}

struct S : P {} // But it gets reported here.

Charles

···

On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:

I definitely think Vladimir's suggestion is a great starting point, IMO.

However, I think it could be improved in one key respect where previous
proposals using `override` are superior. Namely, the proposed `implement`
keyword adds no additional safety when a type implements a protocol
requirement that doesn't have a default implementation. This is because, if

Yes, *at the moment of writing* the type's code there could be no default implementation for protocol requirement. But, *at the moment of compilation* such default implementation could appear.

Let's discuss such scenario in case we'll take your suggestion:

You got SomeClass.swift file, 3rd party file you don't want to change or changes are not allowed. Content:

public protocol SomeProtocol {
  func foo()
}

public class SomeClass : SomeProtocol {
  func foo() {...} // no default implementation *at the moment of writing*, no need in `overload`
}

Now, you adds SomeClass.swift file to your project and in some *other* file you write:

extension SomeProtocol {
  func foo() {...}
}

As you see, you don't control the SomeClass.swift but you suggest in this case SomeClass.foo() should be defined with `override`.

With 'implement' SomeClass.foo() will be marked initially and will save us if protocol's requirement PLUS default implementation changed.

It feels to me like it’s about the ordering (preference) of overloads for method lookups on types. vOv

  Daniel.

···

On 20 Sep 2016, at 02:25, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Sep 19, 2016 at 7:15 PM, Boris Wang <kona.ming@gmail.com> wrote:
I don't think "override" is a good idea. It's not overriding.

Protocol is not Class.

I think you make a good point. It seems like people have generally written about "overriding" default implementations, but that might not be the best term and it may be a little confusing. Is there a “more correct" word for this scenario?

Hello everybody,

Several suggestions are floating around about explicitly marking a method to implement a protocol requirement.

E.g.:

class Foo : Bar {
  implement func foo() {...}
}

However, with extensions we can already do something very similar:

   class Foo {
       ....
   }
   extension Foo: Bar {
       func foo() {...}
   }

Maybe simply adding a new warning would already help.
Extensions which introduce new protocol conformances could be reserved for those methods which are already defined within the protocol. Whenever such an extension contains an unrecognized method, we could issue a warning.
Or maybe even an error, but we should allow private methods as an exception (for helper functions which are clearly not related to the protocol).

This way, when the programmer wants to make sure that her new method is used by a protocol then she can simply put that method in an extension.

···

--
Martin

extension P {

> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another suggestion) in protocol extension also just for the same reasons - be clear about our intention regarding implementing the requirement, to show that this func *depends* on the previous definition of P protocol and to avoid possible mistakes related to protocol conformance.

···

On 20.09.2016 17:38, Charles Srstka wrote:

On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:

I definitely think Vladimir's suggestion is a great starting point, IMO.

However, I think it could be improved in one key respect where previous
proposals using `override` are superior. Namely, the proposed `implement`
keyword adds no additional safety when a type implements a protocol
requirement that doesn't have a default implementation. This is because, if

Yes, *at the moment of writing* the type's code there could be no default
implementation for protocol requirement. But, *at the moment of
compilation* such default implementation could appear.

Let's discuss such scenario in case we'll take your suggestion:

You got SomeClass.swift file, 3rd party file you don't want to change or
changes are not allowed. Content:

public protocol SomeProtocol {
func foo()
}

public class SomeClass : SomeProtocol {
func foo() {...} // no default implementation *at the moment of writing*,
no need in `overload`
}

Now, you adds SomeClass.swift file to your project and in some *other*
file you write:

extension SomeProtocol {
func foo() {...}
}

As you see, you don't control the SomeClass.swift but you suggest in this
case SomeClass.foo() should be defined with `override`.

With 'implement' SomeClass.foo() will be marked initially and will save
us if protocol's requirement PLUS default implementation changed.

Requiring the ‘implement’ keyword can help us even if no default
implementation is involved. Consider:

protocol P {
func foo() -> [String : Any]
}

struct S : P {
func foo() -> [String : String] { return [:] }
}

We will get an error here that S does not conform to P. However, this is
not the correct error, since S in fact *tries* to conform to P, but it has
a mistake in a method signature. This misleads us as to the true nature of
the problem, and if S has enough members in it that we fail to spot the
existing foo(), we might solve the problem by reimplementing foo(), and
leaving the original foo() as dangling dead code. Having an ‘implement’
keyword on the existing foo() function would change the compiler error to
let us know that we have an existing foo() that is incorrectly declared.

In addition, ‘implement’ can help us when the declaration in question *is*
the default implementation:

protocol P {
func foo() -> [String : Any]
}

extension P {
implement func foo() -> [String : String] { return [:] }
}

Here we will get an error with the proposed ‘implement’ keyword, because
foo() does not have a signature matching anything in the protocol, whereas
without ‘implement’ we would happily and silently generate a useless
dangling function that would never be used, and then pass the buck to the
concrete type that implements P:

protocol P {
func foo() -> [String : Any]
}

extension P {
func foo() -> [String : String] { return [:] } // The error is here:
}

struct S : P {} // But it gets reported here.

Charles

I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol,
that means it has all the members specified in the protocol. The protocol
conformance simply codifies a fact about the type itself: namely that all
those members are present.

In this model, any keyword such as `implements` on each conforming member
would introduce substantial boilerplate for negligible gain. The purpose of
a protocol is to communicate that certain members are available, not to
make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is
actual implementation being inherited. A conforming type may choose to roll
its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define
(or redefine!) default implementations for members of that other protocol.
This can create “inheritance chains” of protocol default implementations. I
think there is value in being able to refer to (and call) the inherited
default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol
is in large part merely a convenience: a courtesy so that each conforming
type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some
attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put
forth, I come down firmly on the side of no keyword for protocol
conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

···

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

As I mentioned above, I agree that better diagnostics for near-misses are
necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be
clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point,
IMO.
>>>
>>> However, I think it could be improved in one key respect where
previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change
or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in
this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it
has
> a mistake in a method signature. This misleads us as to the true nature
of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error
to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question
*is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to
the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
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

I think that's a simple and elegant solution. The private member exception
can be extended so that any member with less visibility than the minimum of
the type and protocol visibility would be allowed.

···

On Tue, Sep 20, 2016 at 09:48 Martin Waitz <tali@admingilde.org> wrote:

Hello everybody,

Several suggestions are floating around about explicitly marking a
method to implement a protocol requirement.

E.g.:

> class Foo : Bar {
> implement func foo() {...}
> }

However, with extensions we can already do something very similar:

   class Foo {
       ....
   }
   extension Foo: Bar {
       func foo() {...}
   }

Maybe simply adding a new warning would already help.
Extensions which introduce new protocol conformances could be reserved
for those methods which are already defined within the protocol.
Whenever such an extension contains an unrecognized method, we could
issue a warning.
Or maybe even an error, but we should allow private methods as an
exception (for helper functions which are clearly not related to the
protocol).

This way, when the programmer wants to make sure that her new method is
used by a protocol then she can simply put that method in an extension.

--
Martin

As I mentioned above, I agree that better diagnostics for near-misses are
necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

···

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution > >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point,
IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in
this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it
has
> a mistake in a method signature. This misleads us as to the true nature
of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question
*is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

+1. This is the cleanest proposed solution I've seen to this problem. Like
many people, I've started breaking up a lot of my large classes like view
controllers that have multiple protocol conformances into separate
extensions, and this would let many of those diagnostics fall out naturally.

···

On Tue, Sep 20, 2016 at 7:50 AM Martin Waitz via swift-evolution < swift-evolution@swift.org> wrote:

Hello everybody,

Several suggestions are floating around about explicitly marking a
method to implement a protocol requirement.

E.g.:

> class Foo : Bar {
> implement func foo() {...}
> }

However, with extensions we can already do something very similar:

   class Foo {
       ....
   }
   extension Foo: Bar {
       func foo() {...}
   }

Maybe simply adding a new warning would already help.
Extensions which introduce new protocol conformances could be reserved
for those methods which are already defined within the protocol.
Whenever such an extension contains an unrecognized method, we could
issue a warning.
Or maybe even an error, but we should allow private methods as an
exception (for helper functions which are clearly not related to the
protocol).

This way, when the programmer wants to make sure that her new method is
used by a protocol then she can simply put that method in an extension.

--
Martin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hello everybody,

Several suggestions are floating around about explicitly marking a method
to implement a protocol requirement.

E.g.:

class Foo : Bar {
    implement func foo() {...}
}

However, with extensions we can already do something very similar:

Yes, I also mentioned it in one of the message. Personally I don't like this solution but I do remember that someone from core team mentioned it.

It allows you to have 'safe' code and 'unsafe' - i.e. where you can be lazy and don't provide more info for compiler and got later the problem with protocol conformance we are discussing here; and you can have 'safe' code in extension - where compiler will help you.

Then, shouldn't we disallow protocol conformance 'in-place' in type's definition? So, if you need to conform to protocol - only extension is the syntax for this. In this case I can understand the idea. Otherwise - can't.

So, if I want safe code this suggestion forces me to break my type's definition to a number of extension blocks.
Right now there is a lot of code was written using 'in-place' conformance and not related to protocol methods in extensions. I believe there will be a lot of work to apply for new rules.

And if I have public methods/props *logically* related to implemented methods of protocol - I'll have to keep them in 'main' definition or in another extension.

Also what about marking default implementation methods in *protocol* extension as was mentioned by Charles Srstka? I.e. in "extension P {...}"

  class Foo {
      ....
  }
  extension Foo: Bar {
      func foo() {...}
  }

Maybe simply adding a new warning would already help.
Extensions which introduce new protocol conformances could be reserved for
those methods which are already defined within the protocol. Whenever such
an extension contains an unrecognized method, we could issue a warning.
Or maybe even an error, but we should allow private methods as an exception
(for helper functions which are clearly not related to the protocol).

This way, when the programmer wants to make sure that her new method is
used by a protocol then she can simply put that method in an extension.

I wonder if *any* developer don't want to be sure the method she defined exactly to implement protocol's requirement will be "used by a protocol".

Something like "I implemented this particular protocol's requirement in my type... but.. you know, if something is changed in that protocol and because of this the method will not play a role of implementation... not a big problem, this is not very important code at all". :-)

···

On 20.09.2016 17:48, Martin Waitz wrote:

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

···

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution > >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.

Yes, to do nothing and to have fragile protocol oriented programming is an another alternative. I can understand your opinion but can't agree.

About IDEs - I believe you know what I want to say ;-) In short - we are discussing Swift *language* and there is not only one IDE in this word and even with it nobody knows how long you will wait for such feature and *if* it will be implemented. So, IMO not an option.

About linters. Imagine you added complex 3rd party source code to your project. You use your own linter with your own rules. You see a number of warnings from your linter in that 3rd party code. Of course, the developer of that code was not using your linter with your settings, so there are a lot of warning. You see some warning regarding "near-miss" methods/properties in different places of that code. So, what next?

How linter will protect your project in this case from the discussed problem? In case developer of that 3rd party sources will have to express intentions - your project will be in safe, or theirs sources will not compile at all.

···

On 20.09.2016 19:43, Nevin Brackett-Rozinsky via swift-evolution wrote:

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol,
that means it has all the members specified in the protocol. The protocol
conformance simply codifies a fact about the type itself: namely that all
those members are present.

In this model, any keyword such as `implements` on each conforming member
would introduce substantial boilerplate for negligible gain. The purpose of
a protocol is to communicate that certain members are available, not to
make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is
actual implementation being inherited. A conforming type may choose to roll
its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define
(or redefine!) default implementations for members of that other protocol.
This can create “inheritance chains” of protocol default implementations. I
think there is value in being able to refer to (and call) the inherited
default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol
is in large part merely a convenience: a courtesy so that each conforming
type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some
attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put
forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    As I mentioned above, I agree that better diagnostics for near-misses
    are necessary, but they are possible without new syntax. There is no
    win in avoiding unintentional behavior because, without a default
    implementation, these issues are caught at compile time already.

    On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

         > extension P {
         > implement func foo() -> [String : String] { return [:] }
         > }

        Yes, it seems like we need `implement` (or `override` as another
        suggestion) in protocol extension also just for the same reasons -
        be clear
        about our intention regarding implementing the requirement, to show
        that
        this func *depends* on the previous definition of P protocol and to
        avoid
        possible mistakes related to protocol conformance.

        On 20.09.2016 17:38, Charles Srstka wrote:
        >> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution > >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> > <mailto:swift-evolution@swift.org > <mailto:swift-evolution@swift.org>>> wrote:
        >>
        >> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
        >>> I definitely think Vladimir's suggestion is a great starting
        point, IMO.
        >>>
        >>> However, I think it could be improved in one key respect where
        previous
        >>> proposals using `override` are superior. Namely, the proposed
        `implement`
        >>> keyword adds no additional safety when a type implements a protocol
        >>> requirement that doesn't have a default implementation. This is
        because, if
        >>
        >> Yes, *at the moment of writing* the type's code there could be
        no default
        >> implementation for protocol requirement. But, *at the moment of
        >> compilation* such default implementation could appear.
        >>
        >> Let's discuss such scenario in case we'll take your suggestion:
        >>
        >> You got SomeClass.swift file, 3rd party file you don't want to
        change or
        >> changes are not allowed. Content:
        >>
        >> public protocol SomeProtocol {
        >> func foo()
        >> }
        >>
        >> public class SomeClass : SomeProtocol {
        >> func foo() {...} // no default implementation *at the moment of
        writing*,
        >> no need in `overload`
        >> }
        >>
        >> Now, you adds SomeClass.swift file to your project and in some
        *other*
        >> file you write:
        >>
        >> extension SomeProtocol {
        >> func foo() {...}
        >> }
        >>
        >> As you see, you don't control the SomeClass.swift but you
        suggest in this
        >> case SomeClass.foo() should be defined with `override`.
        >>
        >> With 'implement' SomeClass.foo() will be marked initially and
        will save
        >> us if protocol's requirement PLUS default implementation changed.
        >
        > Requiring the ‘implement’ keyword can help us even if no default
        > implementation is involved. Consider:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > struct S : P {
        > func foo() -> [String : String] { return [:] }
        > }
        >
        > We will get an error here that S does not conform to P. However,
        this is
        > not the correct error, since S in fact *tries* to conform to P,
        but it has
        > a mistake in a method signature. This misleads us as to the true
        nature of
        > the problem, and if S has enough members in it that we fail to
        spot the
        > existing foo(), we might solve the problem by reimplementing
        foo(), and
        > leaving the original foo() as dangling dead code. Having an
        ‘implement’
        > keyword on the existing foo() function would change the compiler
        error to
        > let us know that we have an existing foo() that is incorrectly
        declared.
        >
        > In addition, ‘implement’ can help us when the declaration in
        question *is*
        > the default implementation:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > implement func foo() -> [String : String] { return [:] }
        > }
        >
        > Here we will get an error with the proposed ‘implement’ keyword,
        because
        > foo() does not have a signature matching anything in the
        protocol, whereas
        > without ‘implement’ we would happily and silently generate a useless
        > dangling function that would never be used, and then pass the
        buck to the
        > concrete type that implements P:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > func foo() -> [String : String] { return [:] } // The error is here:
        > }
        >
        > struct S : P {} // But it gets reported here.
        >
        > Charles
        >
        _______________________________________________
        swift-evolution mailing list
        swift-evolution@swift.org <mailto:swift-evolution@swift.org>
        https://lists.swift.org/mailman/listinfo/swift-evolution
        <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    https://lists.swift.org/mailman/listinfo/swift-evolution
    <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

You can’t completely restrict protocol conformance to extensions, because extensions can’t contained stored properties. Thus, to satisfy a protocol requirement with a stored property, it must be placed in the type’s definition.

Charles

···

On Sep 20, 2016, at 10:56 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

Then, shouldn't we disallow protocol conformance 'in-place' in type's definition? So, if you need to conform to protocol - only extension is the syntax for this. In this case I can understand the idea. Otherwise - can't.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

...

CC-ing Dave A, to understand better if this fits with the vision of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should be
to define the entity in an extension that also adds conformance to P.
If that's inadequate indication in some way we should find a way to
enhance it. I wouldn't mind the notation above, but only as a fallback,
not a reuquirement.

···

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

--
-Dave

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

>>
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

···

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

Then, shouldn't we disallow protocol conformance 'in-place' in type's
definition? So, if you need to conform to protocol - only extension is
the syntax for this. In this case I can understand the idea. Otherwise -
can't.

You can’t completely restrict protocol conformance to extensions, because
extensions can’t contained stored properties. Thus, to satisfy a protocol
requirement with a stored property, it must be placed in the type’s definition.

Oh, yes, of course.. And as soon as we can have default implementations for props also - this solution can't help compiler to notify us if our property defined as implementation for protocol requirement is not playing this role any more.
Or we we need stored properties in extensions for this idea. As I understand, there were some discussions regarding this.

In any case the solution "protocol conformance in extensions" does not help when we deal with protocol default implementations - we can't say to compiler that this method/prop here exactly as implementation for protocol, not helper method. I.e. in this situation:

protocol A {
     func foov()
}

protocol B : A {
}

extension A {
     func foov() {}
}

extension B {
     // I was expecting this is a default implementation of foov() for B
     // but in reality this is a helper method
     // who knows when this error will be detected
     func foow() {}
}

I think protocol programming should not be so fragile as it is now and so compiler should help in any place where it can help. For now I don't see any better idea than require here some keyword like `override` or `implement`.

···

On 20.09.2016 19:03, Charles Srstka wrote:

On Sep 20, 2016, at 10:56 AM, Vladimir.S via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Charles

I don't understand. Do you feel that this:

class MyClass : MyProto {
     var MyProto.aVariable : Int
     func MyProto.aFunction() { … }
}

better than this:

class MyClass : MyProto {
     implement var aVariable : Int
     implement func aFunction() { … }
}

?

···

On 21.09.2016 0:28, Karl via swift-evolution wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a
protocol, that means it has all the members specified in the protocol.
The protocol conformance simply codifies a fact about the type itself:
namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member
would introduce substantial boilerplate for negligible gain. The purpose
of a protocol is to communicate that certain members are available, not
to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there
is actual implementation being inherited. A conforming type may choose to
roll its own version of a method, or to utilize the default provided by
the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define
(or redefine!) default implementations for members of that other
protocol. This can create “inheritance chains” of protocol default
implementations. I think there is value in being able to refer to (and
call) the inherited default implementation through some sort of `super`
functionality.

On the other hand, the existence of a default implementation in a
protocol is in large part merely a convenience: a courtesy so that each
conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left
as needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves
some attention. Several people have expressed a desire for the compiler
to assist them in determining whether a given member does or does not
meet a protocol requirement. Specifically, when a type conforms to a
protocol with a default implementation, and the type defines a member
with a similar signature, it is not obvious at glance if that member
matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put
forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and
any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    As I mentioned above, I agree that better diagnostics for near-misses
    are necessary, but they are possible without new syntax. There is no
    win in avoiding unintentional behavior because, without a default
    implementation, these issues are caught at compile time already.

    On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

         > extension P {
         > implement func foo() -> [String : String] { return [:] }
         > }

        Yes, it seems like we need `implement` (or `override` as another
        suggestion) in protocol extension also just for the same reasons
        - be clear
        about our intention regarding implementing the requirement, to
        show that
        this func *depends* on the previous definition of P protocol and
        to avoid
        possible mistakes related to protocol conformance.

        On 20.09.2016 17:38, Charles Srstka wrote:
        >> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> <mailto:swift-evolution@swift.org >> <mailto:swift-evolution@swift.org>>> wrote:
        >>
        >> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
        >>> I definitely think Vladimir's suggestion is a great starting
        point, IMO.
        >>>
        >>> However, I think it could be improved in one key respect
        where previous
        >>> proposals using `override` are superior. Namely, the proposed
        `implement`
        >>> keyword adds no additional safety when a type implements a
        protocol
        >>> requirement that doesn't have a default implementation. This
        is because, if
        >>
        >> Yes, *at the moment of writing* the type's code there could be
        no default
        >> implementation for protocol requirement. But, *at the moment of
        >> compilation* such default implementation could appear.
        >>
        >> Let's discuss such scenario in case we'll take your suggestion:
        >>
        >> You got SomeClass.swift file, 3rd party file you don't want to
        change or
        >> changes are not allowed. Content:
        >>
        >> public protocol SomeProtocol {
        >> func foo()
        >> }
        >>
        >> public class SomeClass : SomeProtocol {
        >> func foo() {...} // no default implementation *at the moment
        of writing*,
        >> no need in `overload`
        >> }
        >>
        >> Now, you adds SomeClass.swift file to your project and in some
        *other*
        >> file you write:
        >>
        >> extension SomeProtocol {
        >> func foo() {...}
        >> }
        >>
        >> As you see, you don't control the SomeClass.swift but you
        suggest in this
        >> case SomeClass.foo() should be defined with `override`.
        >>
        >> With 'implement' SomeClass.foo() will be marked initially and
        will save
        >> us if protocol's requirement PLUS default implementation changed.
        >
        > Requiring the ‘implement’ keyword can help us even if no default
        > implementation is involved. Consider:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > struct S : P {
        > func foo() -> [String : String] { return [:] }
        > }
        >
        > We will get an error here that S does not conform to P.
        However, this is
        > not the correct error, since S in fact *tries* to conform to P,
        but it has
        > a mistake in a method signature. This misleads us as to the
        true nature of
        > the problem, and if S has enough members in it that we fail to
        spot the
        > existing foo(), we might solve the problem by reimplementing
        foo(), and
        > leaving the original foo() as dangling dead code. Having an
        ‘implement’
        > keyword on the existing foo() function would change the
        compiler error to
        > let us know that we have an existing foo() that is incorrectly
        declared.
        >
        > In addition, ‘implement’ can help us when the declaration in
        question *is*
        > the default implementation:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > implement func foo() -> [String : String] { return [:] }
        > }
        >
        > Here we will get an error with the proposed ‘implement’
        keyword, because
        > foo() does not have a signature matching anything in the
        protocol, whereas
        > without ‘implement’ we would happily and silently generate a
        useless
        > dangling function that would never be used, and then pass the
        buck to the
        > concrete type that implements P:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > func foo() -> [String : String] { return [:] } // The error is
        here:
        > }
        >
        > struct S : P {} // But it gets reported here.
        >
        > Charles
        >
        _______________________________________________
        swift-evolution mailing list
        swift-evolution@swift.org <mailto:swift-evolution@swift.org>
        https://lists.swift.org/mailman/listinfo/swift-evolution
        <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    https://lists.swift.org/mailman/listinfo/swift-evolution
    <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree that a new keyword is unwanted. Conforming to protocols is quite a
common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g.
“extension MyClass.MyInternalClass”). It will be easy for autocompletion to
provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function
called `aFunction()`? What if the same name satisfies 2 protocols, which do
you write?

The way to solve all of the problems in a consistent way is to make the
function actually called “MyProto.aFunction”, and for it to be a separate
function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some
complex data structure and it has its own API, but I want people to be able
to view it as a Collection. By conforming to Collection, I reserve lots of
keywords and indexing operations which I now can’t use in my own API. Maybe
I’m just providing Collection as a convenience to work with generic
algorithms, but my own API has more efficient semantics for some
operations. We’re relegated to using less-obvious and legible names in
order to avoid conflicts.

We have a way to work around this, which String uses - create a struct
which references your object and calls internal methods such as
“_collection_count” so you can have separate interfaces. This adds up to
quite a lot of boilerplate and maintenance overhead.

I don’t agree that Protocol conformances are kind-of incidental, as others
here have written. This isn’t like Objective-C where anything that has the
correctly-named methods conforms. Protocol conformances are completely
explicit, and in fact we have empty protocols (“marker protocols”) for
exactly that purpose. I think it is consistent that we make every member of
a conformance specify which protocol it belongs to, and to have its name
scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

...

CC-ing Dave A, to understand better if this fits with the vision of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should be
to define the entity in an extension that also adds conformance to P.

Could you clarify, how do you see a solution in case extension can't have stored properties? So, if protocol has such requirement(i.e. we want to implement the protocol requirement as stored property) we can't move it to extension.
Do you expect we'll have stored props in extension in near future?

Also, what about protocol extensions? What do you suggest to mark default implementation method here to express intention and to separate default implementation (that depends on protocol definition and so, IMO compiler should help us if protocol definition changed) from just helper methods in protocol extension? Like here:

protocol A {
     func foov()
}

protocol B : A {
}

extension A {
     func foov() {}
}

extension B {
     // I was expecting this is a default implementation of foov() for B
     // but in reality this is a helper method
     // who knows when this error will be detected
     func foow() {}
}

If that's inadequate indication in some way we should find a way to
enhance it. I wouldn't mind the notation above, but only as a fallback,
not a reuquirement.

Could you share your opinion (and probably some common opinion of the core team) regarding `implement`(or `override`) keyword requirement for methods/props in type declared exactly to implement protocol's requirements?

Don't you feel that if Swift will not *require* this, we'll have fragile code base as, even if *I* can use linter for this, 3rd party source code that will be in my project probably will not use the "safe" method of protocol conformance?

···

On 21.09.2016 2:34, Dave Abrahams via swift-evolution wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

Indeed this is exactly how C# handles Interfaces (protocols). The default is the exact same way Swift works - by matching names. If there is a collision you specify Protocol.memberName. Its simple and in the years I was writing C# code it was flexible enough to cover most reasonable scenarios, without adding a bunch of boilerplate.

Russ

···

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
   var aVariable : Int
   func aFunction()
}
class MyClass : MyProto {
   var MyProto.aVariable : Int
   func MyProto.aFunction() { … }
}

...

CC-ing Dave A, to understand better if this fits with the vision of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should be
to define the entity in an extension that also adds conformance to P.
If that's inadequate indication in some way we should find a way to
enhance it. I wouldn't mind the notation above, but only as a fallback,
not a reuquirement.

--
-Dave
_______________________________________________

I'm not sure I understand. What compiler or language support is missing for
StringCore?

···

On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution < swift-evolution@swift.org> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution < > swift-evolution@swift.org> wrote:

I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a
protocol, that means it has all the members specified in the protocol. The
protocol conformance simply codifies a fact about the type itself: namely
that all those members are present.

In this model, any keyword such as `implements` on each conforming member
would introduce substantial boilerplate for negligible gain. The purpose of
a protocol is to communicate that certain members are available, not to
make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is
actual implementation being inherited. A conforming type may choose to roll
its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define
(or redefine!) default implementations for members of that other protocol.
This can create “inheritance chains” of protocol default implementations. I
think there is value in being able to refer to (and call) the inherited
default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol
is in large part merely a convenience: a courtesy so that each conforming
type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some
attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put
forth, I come down firmly on the side of no keyword for protocol
conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

As I mentioned above, I agree that better diagnostics for near-misses are
necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be
clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point,
IMO.
>>>
>>> However, I think it could be improved in one key respect where
previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change
or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in
this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will
save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this
is
> not the correct error, since S in fact *tries* to conform to P, but it
has
> a mistake in a method signature. This misleads us as to the true
nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error
to
> let us know that we have an existing foo() that is incorrectly
declared.
>
> In addition, ‘implement’ can help us when the declaration in question
*is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword,
because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to
the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree that a new keyword is unwanted. Conforming to protocols is quite a
common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g.
“extension MyClass.MyInternalClass”). It will be easy for autocompletion to
provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function
called `aFunction()`? What if the same name satisfies 2 protocols, which do
you write?

The way to solve all of the problems in a consistent way is to make the
function actually called “MyProto.aFunction”, and for it to be a separate
function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have
some complex data structure and it has its own API, but I want people to be
able to view it as a Collection. By conforming to Collection, I reserve
lots of keywords and indexing operations which I now can’t use in my own
API. Maybe I’m just providing Collection as a convenience to work with
generic algorithms, but my own API has more efficient semantics for some
operations. We’re relegated to using less-obvious and legible names in
order to avoid conflicts.

We have a way to work around this, which String uses - create a struct
which references your object and calls internal methods such as
“_collection_count” so you can have separate interfaces. This adds up to
quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing
manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and
defines some internal functions to support it.

The String views could then be made in to protocols on String, turning
“UTF8View” in to “UTF8Representable”, and opening up algorithms which can
work on generic sequences of UTF8 bytes. I think that’s pretty cool, and
could open up better integration with other types which are (for example)
UTF8Representable — for example a stream of UTF8 bytes (depending on how
flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others
here have written. This isn’t like Objective-C where anything that has the
correctly-named methods conforms. Protocol conformances are completely
explicit, and in fact we have empty protocols (“marker protocols”) for
exactly that purpose. I think it is consistent that we make every member of
a conformance specify which protocol it belongs to, and to have its name
scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of
protocols

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution