[Review] SE-0070: Make Optional Requirements Objective-C only


(James F) #1

Eliminating optional protocol requirements is fine by me. The proposal mentions ‘correcting’ the optional protocol requirement pattern by changing the methods to optional closure properties, but my feeling is that this ‘solution’ just acts to continue and perhaps encourage the anti-pattern established by ObjC. I think a native Swift design would be much better off using optional closure properties on the table view itself.

A common theme in these ObjC optional protocol requirements is the first parameter being an instance whichever class ‘requires’ the method. Yet on the rare occasion of the instance potentially having more than one value, the implementation for each instance is often so different that my first action will be to add a switch between the possible instances (which, of course, means having those components available as IBOutlet properties anyway).

I suggest a much better solution to optional protocol requirements in Swift is the creation of wrappers for UIKit components. These would implement the protocol requirements, and expose optional closure properties for their their public API. Making them properties makes it far clearer that the behaviour of the container will change if a value is provided, and would remove the persistent need to apply @objc to any Swift types dealing with UIKit. I understand this would be a manual task, but I just don't think there is a good automatic solution to this problem.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <A57B248C-9679-450A-A09D-8C0A5E3846E8@apple.com>

Hello Swift community,

The review of "SE-0070: Make Optional Requirements Objective-C only" begins now and runs through May 2. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0070-optional-requirements.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

* What is your evaluation of the proposal?
* Is the problem being addressed significant enough to warrant a change to Swift?
* Does this proposal fit well with the feel and direction of Swift?
* If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
* How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager

···

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

------------- End Message -------------

From James F

From James F


(Douglas Gregor) #2

Eliminating optional protocol requirements is fine by me. The proposal mentions ‘correcting’ the optional protocol requirement pattern by changing the methods to optional closure properties, but my feeling is that this ‘solution’ just acts to continue and perhaps encourage the anti-pattern established by ObjC. I think a native Swift design would be much better off using optional closure properties on the table view itself.

A common theme in these ObjC optional protocol requirements is the first parameter being an instance whichever class ‘requires’ the method. Yet on the rare occasion of the instance potentially having more than one value, the implementation for each instance is often so different that my first action will be to add a switch between the possible instances (which, of course, means having those components available as IBOutlet properties anyway).

I suggest a much better solution to optional protocol requirements in Swift is the creation of wrappers for UIKit components. These would implement the protocol requirements, and expose optional closure properties for their their public API. Making them properties makes it far clearer that the behaviour of the container will change if a value is provided, and would remove the persistent need to apply @objc to any Swift types dealing with UIKit. I understand this would be a manual task, but I just don't think there is a good automatic solution to this problem.

There are ~800 optional requirements in the iOS SDK and ~1000 in the OS X SDK. That too large a manual task to accomplish.

Also, I think the arguments in the proposal against the optional-closure-properties approach are fairly strong: it doesn’t seem like a good way to model Objective-C optional requirements.

  - Doug

···

On Apr 25, 2016, at 12:18 PM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <A57B248C-9679-450A-A09D-8C0A5E3846E8@apple.com>

Hello Swift community,

The review of "SE-0070: Make Optional Requirements Objective-C only" begins now and runs through May 2. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0070-optional-requirements.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

* What is your evaluation of the proposal?
* Is the problem being addressed significant enough to warrant a change to Swift?
* Does this proposal fit well with the feel and direction of Swift?
* If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
* How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
� �

------------- End Message -------------

From James F

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


(James F) #3

Fair enough. Upon reflection, I think my real issue is somewhat different to what I suggested previously.

I wasn't intending to suggest such a thing would be practical, just that it would be a decent alternative to optional protocol requirements. The alternative given in the proposal seems to be more of a way to remove optional protocol requirements on the surface, while actually helping to make them a native feature, if you see what I mean. It's not a realistic alternative - it's a worse syntax for the exact same thing, which also comes with awful side-effects for Swift as a whole. No-one would ever seriously consider this as an alternative, yet it's listed as under the heading ‘Alternatives Considered’.

You say the arguments given against optional closure properties are strong, but I don't they would be nearly as relevant to the case I suggested. By making them properties of the table view, the tableView parameter would be eliminated, meaning the property names could be unique.

EG:
var numberOfRows: (inSection: Int) -> Int
var cellForRow:: (at: NSIndexPath) -> UITableViewCell
var moveRow: (from: NSIndexPath, to: NSIndexPath)

This removes the need to add the mentioned workarounds, since a function could be assigned to the closure property just as easily as an inline closure. I feel this is much more worthy of being considered as an alternative. The idea of these proposals is to document why we do things, so at least for someone wondering why we require all this @objc syntax rather than support optional protocol requirements natively, this would actually present them with a viable alternative which could be applied in their APIs.

Thanks for the consideration of my previous email. Sorry for being a bit pedantic, but I do feel there's something off about the proposal as it is written, for it to completely fail to provide any realistic alternative to optional protocol requirements that can be applied by future Swift developers.

From James F

···

On 26 Apr 2016, at 04:06, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 25, 2016, at 12:18 PM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Eliminating optional protocol requirements is fine by me. The proposal mentions ‘correcting’ the optional protocol requirement pattern by changing the methods to optional closure properties, but my feeling is that this ‘solution’ just acts to continue and perhaps encourage the anti-pattern established by ObjC. I think a native Swift design would be much better off using optional closure properties on the table view itself.

A common theme in these ObjC optional protocol requirements is the first parameter being an instance whichever class ‘requires’ the method. Yet on the rare occasion of the instance potentially having more than one value, the implementation for each instance is often so different that my first action will be to add a switch between the possible instances (which, of course, means having those components available as IBOutlet properties anyway).

I suggest a much better solution to optional protocol requirements in Swift is the creation of wrappers for UIKit components. These would implement the protocol requirements, and expose optional closure properties for their their public API. Making them properties makes it far clearer that the behaviour of the container will change if a value is provided, and would remove the persistent need to apply @objc to any Swift types dealing with UIKit. I understand this would be a manual task, but I just don't think there is a good automatic solution to this problem.

There are ~800 optional requirements in the iOS SDK and ~1000 in the OS X SDK. That too large a manual task to accomplish.

Also, I think the arguments in the proposal against the optional-closure-properties approach are fairly strong: it doesn’t seem like a good way to model Objective-C optional requirements.

   - Doug

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <A57B248C-9679-450A-A09D-8C0A5E3846E8@apple.com>

Hello Swift community,

The review of "SE-0070: Make Optional Requirements Objective-C only" begins now and runs through May 2. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0070-optional-requirements.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

* What is your evaluation of the proposal?
* Is the problem being addressed significant enough to warrant a change to Swift?
* Does this proposal fit well with the feel and direction of Swift?
* If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
* How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
� �

------------- End Message -------------

From James F

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


(Douglas Gregor) #4

Fair enough. Upon reflection, I think my real issue is somewhat different to what I suggested previously.

I wasn't intending to suggest such a thing would be practical, just that it would be a decent alternative to optional protocol requirements. The alternative given in the proposal seems to be more of a way to remove optional protocol requirements on the surface, while actually helping to make them a native feature, if you see what I mean. It's not a realistic alternative - it's a worse syntax for the exact same thing, which also comes with awful side-effects for Swift as a whole. No-one would ever seriously consider this as an alternative, yet it's listed as under the heading ‘Alternatives Considered’.

If you follow the swift-evolution discussion links in the proposal, you’ll note that a number of people have proposed exactly what is listed in “Alternatives Considered”. The only truly wacky idea in there is my caller-side default implementations idea, which I covered simply because it was my last stab at eliminating optional requirements before giving up and sequestering them permanently behind “@objc”.

You say the arguments given against optional closure properties are strong, but I don't they would be nearly as relevant to the case I suggested. By making them properties of the table view, the tableView parameter would be eliminated, meaning the property names could be unique.

EG:
var numberOfRows: (inSection: Int) -> Int
var cellForRow:: (at: NSIndexPath) -> UITableViewCell
var moveRow: (from: NSIndexPath, to: NSIndexPath)

This removes the need to add the mentioned workarounds, since a function could be assigned to the closure property just as easily as an inline closure. I feel this is much more worthy of being considered as an alternative. The idea of these proposals is to document why we do things, so at least for someone wondering why we require all this @objc syntax rather than support optional protocol requirements natively, this would actually present them with a viable alternative which could be applied in their APIs.

Doing this implies creating a potentially large number of stored closure properties, which is not as storage-efficient as storing a single delegate reference. Moreover, it makes it harder to set up your customization points: instead of implementing one protocol, you’re writing assignments into some number of stored closure properties. Imaging trying to change the delegate to some other delegate temporarily: you would have to manually store each of the closures into some local structure and introduce your own, except that you can’t get them all because some new version of the platform would add new stored closure properties. Finally, Cocoa just doesn’t work like this, so you would require some massive re-architecture to get there. I don’t see how this is a better design.

  - Doug

···

On Apr 26, 2016, at 3:33 AM, James Froggatt <conductator@ntlworld.com> wrote:


(James F) #5

Thanks again.

I had a look at the links in the proposal as you suggested, and I see a lot of people pointing to protocol extensions as a solution (and counter-arguments of the inability to optimise code with this method, which are left unresolved).

To make use of the protocol extensions solution, one would have to define the protocol, add a protocol extension which implements every function, then add an empty type which allows access to these implementations.
For a recommended alternative, this seems a lot of work. In a world where Swift didn't have Objective C compatibility, and this empty-type workaround to access defaults was the best option available, I'd be inclined to support a proposal to add optional method requirements. It has the added optimisation and easy delegate-swapping relative to closure properties, as you mentioned, and feels less hacky than the closure-function switching suggested in the proposal.

The protocol extension + default type would provide a direct alternative, but it leads me to wonder what exactly we're trying to avoid by discouraging optional methods. The potential for unexpected optimisation, which seems to be the primary issue, is unsolved, since the type can check to see if the delegate is its own, default type, and proceed to ignore the method regardless. In exchange, we make things much harder for types simply wishing to have a default value when there is no registered delegate.

So what aspect of optional protocol requirements are we actually trying to discourage, which isn't present in protocol extensions?

PS. If we're concerned about overlap with protocol extensions: it seems a bit like eliminating functions from the language because they overlap with the more general concept of closures. It's a fine idea, but it seems more reasonable to find a solution that handles both cases conveniently before we start eliminating one of them.

From James F

···

On 26 Apr 2016, at 22:56, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 26, 2016, at 3:33 AM, James Froggatt <conductator@ntlworld.com> wrote:

Fair enough. Upon reflection, I think my real issue is somewhat different to what I suggested previously.

I wasn't intending to suggest such a thing would be practical, just that it would be a decent alternative to optional protocol requirements. The alternative given in the proposal seems to be more of a way to remove optional protocol requirements on the surface, while actually helping to make them a native feature, if you see what I mean. It's not a realistic alternative - it's a worse syntax for the exact same thing, which also comes with awful side-effects for Swift as a whole. No-one would ever seriously consider this as an alternative, yet it's listed as under the heading ‘Alternatives Considered’.

If you follow the swift-evolution discussion links in the proposal, you’ll note that a number of people have proposed exactly what is listed in “Alternatives Considered”. The only truly wacky idea in there is my caller-side default implementations idea, which I covered simply because it was my last stab at eliminating optional requirements before giving up and sequestering them permanently behind “@objc”.

You say the arguments given against optional closure properties are strong, but I don't they would be nearly as relevant to the case I suggested. By making them properties of the table view, the tableView parameter would be eliminated, meaning the property names could be unique.

EG:
var numberOfRows: (inSection: Int) -> Int
var cellForRow:: (at: NSIndexPath) -> UITableViewCell
var moveRow: (from: NSIndexPath, to: NSIndexPath)

This removes the need to add the mentioned workarounds, since a function could be assigned to the closure property just as easily as an inline closure. I feel this is much more worthy of being considered as an alternative. The idea of these proposals is to document why we do things, so at least for someone wondering why we require all this @objc syntax rather than support optional protocol requirements natively, this would actually present them with a viable alternative which could be applied in their APIs.

Doing this implies creating a potentially large number of stored closure properties, which is not as storage-efficient as storing a single delegate reference. Moreover, it makes it harder to set up your customization points: instead of implementing one protocol, you’re writing assignments into some number of stored closure properties. Imaging trying to change the delegate to some other delegate temporarily: you would have to manually store each of the closures into some local structure and introduce your own, except that you can’t get them all because some new version of the platform would add new stored closure properties. Finally, Cocoa just doesn’t work like this, so you would require some massive re-architecture to get there. I don’t see how this is a better design.

  - Doug


(Andrew Bennett) #6

Sorry if this has been discussed, but have you considered dropping optional
entirely, making it throw, and a default implementation that throws a
selector not found exception?

This is approximately what you would expect using it in objc. I don't think
it has the complexity discussed in the proposals alternatives for other
call site issues.

If it throws you can call with "try?" to get similar functionality in most
cases.

This assumes that respondsToSelector doesn't pick up the Swift default
implementation.

···

On Wednesday, 27 April 2016, James Froggatt via swift-evolution < swift-evolution@swift.org> wrote:

Thanks again.

I had a look at the links in the proposal as you suggested, and I see a
lot of people pointing to protocol extensions as a solution (and
counter-arguments of the inability to optimise code with this method, which
are left unresolved).

To make use of the protocol extensions solution, one would have to define
the protocol, add a protocol extension which implements every function,
then add an empty type which allows access to these implementations.
For a recommended alternative, this seems a lot of work. In a world where
Swift didn't have Objective C compatibility, and this empty-type workaround
to access defaults was the best option available, I'd be inclined to
support a proposal to add optional method requirements. It has the added
optimisation and easy delegate-swapping relative to closure properties, as
you mentioned, and feels less hacky than the closure-function switching
suggested in the proposal.

The protocol extension + default type would provide a direct alternative,
but it leads me to wonder what exactly we're trying to avoid by
discouraging optional methods. The potential for unexpected optimisation,
which seems to be the primary issue, is unsolved, since the type can check
to see if the delegate is its own, default type, and proceed to ignore the
method regardless. In exchange, we make things much harder for types simply
wishing to have a default value when there is no registered delegate.

So what aspect of optional protocol requirements are we actually trying to
discourage, which isn't present in protocol extensions?

PS. If we're concerned about overlap with protocol extensions: it seems a
bit like eliminating functions from the language because they overlap with
the more general concept of closures. It's a fine idea, but it seems more
reasonable to find a solution that handles both cases conveniently before
we start eliminating one of them.

From James F

> On 26 Apr 2016, at 22:56, Douglas Gregor <dgregor@apple.com > <javascript:;>> wrote:
>
>
>> On Apr 26, 2016, at 3:33 AM, James Froggatt <conductator@ntlworld.com > <javascript:;>> wrote:
>>
>> Fair enough. Upon reflection, I think my real issue is somewhat
different to what I suggested previously.
>>
>> I wasn't intending to suggest such a thing would be practical, just
that it would be a decent alternative to optional protocol requirements.
The alternative given in the proposal seems to be more of a way to remove
optional protocol requirements on the surface, while actually helping to
make them a native feature, if you see what I mean. It's not a realistic
alternative - it's a worse syntax for the exact same thing, which also
comes with awful side-effects for Swift as a whole. No-one would ever
seriously consider this as an alternative, yet it's listed as under the
heading ‘Alternatives Considered’.
>
> If you follow the swift-evolution discussion links in the proposal,
you’ll note that a number of people have proposed exactly what is listed in
“Alternatives Considered”. The only truly wacky idea in there is my
caller-side default implementations idea, which I covered simply because it
was my last stab at eliminating optional requirements before giving up and
sequestering them permanently behind “@objc”.
>
>>
>> You say the arguments given against optional closure properties are
strong, but I don't they would be nearly as relevant to the case I
suggested. By making them properties of the table view, the tableView
parameter would be eliminated, meaning the property names could be unique.
>>
>> EG:
>> var numberOfRows: (inSection: Int) -> Int
>> var cellForRow:: (at: NSIndexPath) -> UITableViewCell
>> var moveRow: (from: NSIndexPath, to: NSIndexPath)
>>
>> This removes the need to add the mentioned workarounds, since a
function could be assigned to the closure property just as easily as an
inline closure. I feel this is much more worthy of being considered as an
alternative. The idea of these proposals is to document why we do things,
so at least for someone wondering why we require all this @objc syntax
rather than support optional protocol requirements natively, this would
actually present them with a viable alternative which could be applied in
their APIs.
>
> Doing this implies creating a potentially large number of stored closure
properties, which is not as storage-efficient as storing a single delegate
reference. Moreover, it makes it harder to set up your customization
points: instead of implementing one protocol, you’re writing assignments
into some number of stored closure properties. Imaging trying to change the
delegate to some other delegate temporarily: you would have to manually
store each of the closures into some local structure and introduce your
own, except that you can’t get them all because some new version of the
platform would add new stored closure properties. Finally, Cocoa just
doesn’t work like this, so you would require some massive re-architecture
to get there. I don’t see how this is a better design.
>
> - Doug
>

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


(Charles Srstka) #7

Is there any case where you’d actually want to display a runtime error as a result of a delegate not implementing an optional method, though? Even setting aside that the method’s supposed to be optional, leaving out a needed delegate method seems more like a programmer error than a runtime error.

Charles

···

On Apr 27, 2016, at 9:30 AM, Andrew Bennett via swift-evolution <swift-evolution@swift.org> wrote:

Sorry if this has been discussed, but have you considered dropping optional entirely, making it throw, and a default implementation that throws a selector not found exception?

This is approximately what you would expect using it in objc. I don't think it has the complexity discussed in the proposals alternatives for other call site issues.

If it throws you can call with "try?" to get similar functionality in most cases.

This assumes that respondsToSelector doesn't pick up the Swift default implementation.


(James F) #8

Interesting idea. I tried this in a playground to see what the calling syntax would be like:

let delegate = Optional(Delegate())
let default = 0
let value: Int = (try? delegate?.returnFive() ?? default) ?? default
value

Not quite as elegant at the call site, but it works. Sadly the rethrowing overload of ?? complicates things, I'm not sure of a way to work around that directly.

I do like that types could potentially implement the function and do something, then throw an error rather than returning a value, which would allow them opt into using the default value. It would complicate matters if the conforming types throw multiple errors for whatever reason, though.

From James F

···

On 27 Apr 2016, at 15:30, Andrew Bennett <cacoyi@gmail.com> wrote:

Sorry if this has been discussed, but have you considered dropping optional entirely, making it throw, and a default implementation that throws a selector not found exception?

This is approximately what you would expect using it in objc. I don't think it has the complexity discussed in the proposals alternatives for other call site issues.

If it throws you can call with "try?" to get similar functionality in most cases.

This assumes that respondsToSelector doesn't pick up the Swift default implementation.

On Wednesday, 27 April 2016, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:
Thanks again.

I had a look at the links in the proposal as you suggested, and I see a lot of people pointing to protocol extensions as a solution (and counter-arguments of the inability to optimise code with this method, which are left unresolved).

To make use of the protocol extensions solution, one would have to define the protocol, add a protocol extension which implements every function, then add an empty type which allows access to these implementations.
For a recommended alternative, this seems a lot of work. In a world where Swift didn't have Objective C compatibility, and this empty-type workaround to access defaults was the best option available, I'd be inclined to support a proposal to add optional method requirements. It has the added optimisation and easy delegate-swapping relative to closure properties, as you mentioned, and feels less hacky than the closure-function switching suggested in the proposal.

The protocol extension + default type would provide a direct alternative, but it leads me to wonder what exactly we're trying to avoid by discouraging optional methods. The potential for unexpected optimisation, which seems to be the primary issue, is unsolved, since the type can check to see if the delegate is its own, default type, and proceed to ignore the method regardless. In exchange, we make things much harder for types simply wishing to have a default value when there is no registered delegate.

So what aspect of optional protocol requirements are we actually trying to discourage, which isn't present in protocol extensions?

PS. If we're concerned about overlap with protocol extensions: it seems a bit like eliminating functions from the language because they overlap with the more general concept of closures. It's a fine idea, but it seems more reasonable to find a solution that handles both cases conveniently before we start eliminating one of them.

From James F

> On 26 Apr 2016, at 22:56, Douglas Gregor <dgregor@apple.com> wrote:
>
>
>> On Apr 26, 2016, at 3:33 AM, James Froggatt <conductator@ntlworld.com> wrote:
>>
>> Fair enough. Upon reflection, I think my real issue is somewhat different to what I suggested previously.
>>
>> I wasn't intending to suggest such a thing would be practical, just that it would be a decent alternative to optional protocol requirements. The alternative given in the proposal seems to be more of a way to remove optional protocol requirements on the surface, while actually helping to make them a native feature, if you see what I mean. It's not a realistic alternative - it's a worse syntax for the exact same thing, which also comes with awful side-effects for Swift as a whole. No-one would ever seriously consider this as an alternative, yet it's listed as under the heading ‘Alternatives Considered’.
>
> If you follow the swift-evolution discussion links in the proposal, you’ll note that a number of people have proposed exactly what is listed in “Alternatives Considered”. The only truly wacky idea in there is my caller-side default implementations idea, which I covered simply because it was my last stab at eliminating optional requirements before giving up and sequestering them permanently behind “@objc”.
>
>>
>> You say the arguments given against optional closure properties are strong, but I don't they would be nearly as relevant to the case I suggested. By making them properties of the table view, the tableView parameter would be eliminated, meaning the property names could be unique.
>>
>> EG:
>> var numberOfRows: (inSection: Int) -> Int
>> var cellForRow:: (at: NSIndexPath) -> UITableViewCell
>> var moveRow: (from: NSIndexPath, to: NSIndexPath)
>>
>> This removes the need to add the mentioned workarounds, since a function could be assigned to the closure property just as easily as an inline closure. I feel this is much more worthy of being considered as an alternative. The idea of these proposals is to document why we do things, so at least for someone wondering why we require all this @objc syntax rather than support optional protocol requirements natively, this would actually present them with a viable alternative which could be applied in their APIs.
>
> Doing this implies creating a potentially large number of stored closure properties, which is not as storage-efficient as storing a single delegate reference. Moreover, it makes it harder to set up your customization points: instead of implementing one protocol, you’re writing assignments into some number of stored closure properties. Imaging trying to change the delegate to some other delegate temporarily: you would have to manually store each of the closures into some local structure and introduce your own, except that you can’t get them all because some new version of the platform would add new stored closure properties. Finally, Cocoa just doesn’t work like this, so you would require some massive re-architecture to get there. I don’t see how this is a better design.
>
> - Doug
>

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


(Andrew Bennett) #9

Hi James,

I don't think it would complicate it any more than a throw normal is. You
can still use a do/catch, with types catches.

···

On Thursday, 28 April 2016, James Froggatt <conductator@ntlworld.com> wrote:

Interesting idea. I tried this in a playground to see what the calling
syntax would be like:

let delegate = Optional(Delegate())
let default = 0
let value: Int = (try? delegate?.returnFive() ?? default) ?? default
value

Not quite as elegant at the call site, but it works. Sadly the rethrowing
overload of ?? complicates things, I'm not sure of a way to work around
that directly.

I do like that types could potentially implement the function and do
something, then throw an error rather than returning a value, which would
allow them opt into using the default value. It would complicate matters if
the conforming types throw multiple errors for whatever reason, though.

From James F

On 27 Apr 2016, at 15:30, Andrew Bennett <cacoyi@gmail.com > <javascript:_e(%7B%7D,'cvml','cacoyi@gmail.com');>> wrote:

Sorry if this has been discussed, but have you considered dropping
optional entirely, making it throw, and a default implementation that
throws a selector not found exception?

This is approximately what you would expect using it in objc. I don't
think it has the complexity discussed in the proposals alternatives for
other call site issues.

If it throws you can call with "try?" to get similar functionality in most
cases.

This assumes that respondsToSelector doesn't pick up the Swift default
implementation.

On Wednesday, 27 April 2016, James Froggatt via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Thanks again.

I had a look at the links in the proposal as you suggested, and I see a
lot of people pointing to protocol extensions as a solution (and
counter-arguments of the inability to optimise code with this method, which
are left unresolved).

To make use of the protocol extensions solution, one would have to define
the protocol, add a protocol extension which implements every function,
then add an empty type which allows access to these implementations.
For a recommended alternative, this seems a lot of work. In a world where
Swift didn't have Objective C compatibility, and this empty-type workaround
to access defaults was the best option available, I'd be inclined to
support a proposal to add optional method requirements. It has the added
optimisation and easy delegate-swapping relative to closure properties, as
you mentioned, and feels less hacky than the closure-function switching
suggested in the proposal.

The protocol extension + default type would provide a direct alternative,
but it leads me to wonder what exactly we're trying to avoid by
discouraging optional methods. The potential for unexpected optimisation,
which seems to be the primary issue, is unsolved, since the type can check
to see if the delegate is its own, default type, and proceed to ignore the
method regardless. In exchange, we make things much harder for types simply
wishing to have a default value when there is no registered delegate.

So what aspect of optional protocol requirements are we actually trying
to discourage, which isn't present in protocol extensions?

PS. If we're concerned about overlap with protocol extensions: it seems a
bit like eliminating functions from the language because they overlap with
the more general concept of closures. It's a fine idea, but it seems more
reasonable to find a solution that handles both cases conveniently before
we start eliminating one of them.

From James F

> On 26 Apr 2016, at 22:56, Douglas Gregor <dgregor@apple.com> wrote:
>
>
>> On Apr 26, 2016, at 3:33 AM, James Froggatt <conductator@ntlworld.com> >> wrote:
>>
>> Fair enough. Upon reflection, I think my real issue is somewhat
different to what I suggested previously.
>>
>> I wasn't intending to suggest such a thing would be practical, just
that it would be a decent alternative to optional protocol requirements.
The alternative given in the proposal seems to be more of a way to remove
optional protocol requirements on the surface, while actually helping to
make them a native feature, if you see what I mean. It's not a realistic
alternative - it's a worse syntax for the exact same thing, which also
comes with awful side-effects for Swift as a whole. No-one would ever
seriously consider this as an alternative, yet it's listed as under the
heading ‘Alternatives Considered’.
>
> If you follow the swift-evolution discussion links in the proposal,
you’ll note that a number of people have proposed exactly what is listed in
“Alternatives Considered”. The only truly wacky idea in there is my
caller-side default implementations idea, which I covered simply because it
was my last stab at eliminating optional requirements before giving up and
sequestering them permanently behind “@objc”.
>
>>
>> You say the arguments given against optional closure properties are
strong, but I don't they would be nearly as relevant to the case I
suggested. By making them properties of the table view, the tableView
parameter would be eliminated, meaning the property names could be unique.
>>
>> EG:
>> var numberOfRows: (inSection: Int) -> Int
>> var cellForRow:: (at: NSIndexPath) -> UITableViewCell
>> var moveRow: (from: NSIndexPath, to: NSIndexPath)
>>
>> This removes the need to add the mentioned workarounds, since a
function could be assigned to the closure property just as easily as an
inline closure. I feel this is much more worthy of being considered as an
alternative. The idea of these proposals is to document why we do things,
so at least for someone wondering why we require all this @objc syntax
rather than support optional protocol requirements natively, this would
actually present them with a viable alternative which could be applied in
their APIs.
>
> Doing this implies creating a potentially large number of stored
closure properties, which is not as storage-efficient as storing a single
delegate reference. Moreover, it makes it harder to set up your
customization points: instead of implementing one protocol, you’re writing
assignments into some number of stored closure properties. Imaging trying
to change the delegate to some other delegate temporarily: you would have
to manually store each of the closures into some local structure and
introduce your own, except that you can’t get them all because some new
version of the platform would add new stored closure properties. Finally,
Cocoa just doesn’t work like this, so you would require some massive
re-architecture to get there. I don’t see how this is a better design.
>
> - Doug
>

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


(Andrew Bennett) #10

Hi Charles,

My initial idea just had a fatalError, without a throw. It's better IMO,
but less Swift-y. It's not obvious from the Swift protocol definition that
this could happen. I'm not sure if it's possible for the extension method
to have @noreturn or similar on it.

···

On Thursday, 28 April 2016, Charles Srstka <cocoadev@charlessoft.com> wrote:

On Apr 27, 2016, at 9:30 AM, Andrew Bennett via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Sorry if this has been discussed, but have you considered dropping
optional entirely, making it throw, and a default implementation that
throws a selector not found exception?

This is approximately what you would expect using it in objc. I don't
think it has the complexity discussed in the proposals alternatives for
other call site issues.

If it throws you can call with "try?" to get similar functionality in most
cases.

This assumes that respondsToSelector doesn't pick up the Swift default
implementation.

Is there any case where you’d actually want to display a runtime error as
a result of a delegate not implementing an optional method, though? Even
setting aside that the method’s supposed to be optional, leaving out a
needed delegate method seems more like a programmer error than a runtime
error.

Charles


(Charles Srstka) #11

Why would you want lack of an optional method to be a fatal error, either?

Charles

···

On Apr 27, 2016, at 5:29 PM, Andrew Bennett <cacoyi@gmail.com> wrote:

Hi Charles,

My initial idea just had a fatalError, without a throw. It's better IMO, but less Swift-y. It's not obvious from the Swift protocol definition that this could happen. I'm not sure if it's possible for the extension method to have @noreturn or similar on it.

On Thursday, 28 April 2016, Charles Srstka <cocoadev@charlessoft.com <mailto:cocoadev@charlessoft.com>> wrote:

On Apr 27, 2016, at 9:30 AM, Andrew Bennett via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Sorry if this has been discussed, but have you considered dropping optional entirely, making it throw, and a default implementation that throws a selector not found exception?

This is approximately what you would expect using it in objc. I don't think it has the complexity discussed in the proposals alternatives for other call site issues.

If it throws you can call with "try?" to get similar functionality in most cases.

This assumes that respondsToSelector doesn't pick up the Swift default implementation.

Is there any case where you’d actually want to display a runtime error as a result of a delegate not implementing an optional method, though? Even setting aside that the method’s supposed to be optional, leaving out a needed delegate method seems more like a programmer error than a runtime error.

Charles