[swift-evolution] [Pitch] Allow closures/default params to satisfy protocol requirements

Slava Pestov spestov at apple.com
Tue Mar 28 21:07:34 CDT 2017


> On Mar 28, 2017, at 12:10 AM, Adrian Zubarev <adrian.zubarev at devandartist.com> wrote:
> 
> It’s probably the influence from iOS development where I have delegate protocols like this one:
> 
> @objc public protocol _ContainerViewControllerDelegate: class {
>      
>     @objc optional func containerViewController(_ containerViewController: ContainerViewController,
>                                                 willPerform operation: ContainerViewController.Operation,
>                                                 from oldViewController: UIViewController,
>                                                 to newViewController: UIViewController,
>                                                 animated: Bool)
>      
>     @objc optional func containerViewController(_ containerViewController: ContainerViewController,
>                                                 didPerform operation: ContainerViewController.Operation,
>                                                 from oldViewController: UIViewController,
>                                                 to newViewController: UIViewController,
>                                                 animated: Bool)
>      
>     @objc optional func containerViewController(_ containerViewController: ContainerViewController,
>                                                 willSet oldViewControllers: [UIViewController],
>                                                 to newViewControllers: [UIViewController],
>                                                 animated: Bool)
>      
>     @objc optional func containerViewController(_ containerViewController: ContainerViewController,
>                                                 didSet newViewControllers: [UIViewController],
>                                                 from oldViewControllers: [UIViewController],
>                                                 animated: Bool)
> }

This looks like a bad API to begin with. If I was designing something like this I would instead have a single containerViewController() method or something that takes a value which encodes the various states.

You could have something like this:

enum ViewControllerState {
  case willPerform(…)
  case didPerform(…)
  case willSet(…)
  case didSet(…)
}

Slava
> Implementing noops for each function in an extension seems kind of a wrong decision for a few reasons:
> 
> They don’t make sense, because either the receiver implements a function or not. So optional functions provide a more natural solution to that problem.
> 
> We don’t have to pass unnecessarily any arguments to the top functions.
> 
> (Personal preference) I tend to avoid @objc in general. 
> 
> I think there was some technical reason why we don’t have optional functions in pure Swift yet, something that also affects dynamic if I’m not mistaken.
> 
> Think of the protocol from above as of an existential of a set of functions. The problem is that, I don’t want to introduce a standalone protocol for every function, so the client can decide which protocol it will conform to to avoid these noops. Furthermore, it’s way easier to check for an optional function in your control flow instead of dealing with default values delegate functions with a more complex return type might have.
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 28. März 2017 um 07:31:50, Slava Pestov (spestov at apple.com <mailto:spestov at apple.com>) schrieb:
> 
>> 
>>> On Mar 27, 2017, at 1:48 PM, Adrian Zubarev via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Assuming we’ll get that functionality, both var and let should satisfy the protocol requirements right?
>>> 
>> In theory, there’s no reason not to allow that.
>> 
>>> If it is valid, could we potentially get optional functions in pure Swift as well?
>>> 
>>> 
>> I mean, you can already do this:
>> 
>> protocol P {
>>   var optionalRequirement: ((Int) -> ())? { get }
>> }
>> 
>> extension P {
>>   // “default implementation"
>>   var optionalRequirement: ((Int) -> ())? { return nil }
>> }
>> 
>> struct A : P {}
>> 
>> struct B : P {
>>   let optionalRequirement: ((Int) -> ())? = { (x: Int) in print(x) }
>> }
>> 
>> But it’s kind of tacky.
>> 
>> If you think about it, “optional requirement” is an oxymoron. What’s your use-case?
>> 
>> Slava
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170328/dacef494/attachment.html>


More information about the swift-evolution mailing list