[swift-evolution] Will Swift ever support optional methods without @objc?

Shawn Erickson shawnce at gmail.com
Tue Nov 15 21:37:42 CST 2016


I think you are fixating on my talk about imp caching instead of my main
point about setting up the state of my delegator to avoid unneeded work
when a registered delegate hasn't implement a delegation point. It an
unrelated topic to what is being discussed.

-Shawn

On Tue, Nov 15, 2016 at 5:27 PM Karl <razielim at gmail.com> wrote:

>
> On 15 Nov 2016, at 19:38, Shawn Erickson <shawnce at gmail.com> wrote:
>
> Using sub-protocols may be sufficient and make sense... to be honest I
> haven't had the time to fully explore this space and convert some things I
> have done in objective-c to pure swift. I do wonder how often that those
> sub-protocols would degenerate into having single methods.
>
> In a nut shell it isn't atypical for a delegate to only care about
> "injecting itself" (e.g. implementing a delegate function) for a subset of
> the available delegation points leaving the others unimplemented. In the
> objective-c case the delegator can evaluate what delegation points a
> delegate implements at time of delegate registration (or more dynamically
> ... however I often did imp caching for performance reasons in some of my
> designs). This probe on delegate registration may make sense for the
> delegator if additional bookkeeping, processing, state management, or
> potentially whole code path/objects can be avoided if the delegate doesn't
> implement a delegation point(s). If the delegation points happened to be
> implemented using a default nop implementation this type of optimization
> may not be possible.
>
> In a nutshell I see and have the need for the delegator to know if the
> delegate has actually provided an implementation of their own or not so I
> can potentially leverage optimizations internal to my delegator. As a
> delegate is also nice to know clearly what I have to implement or not and
> the optional protocol member concept is one way of doing that, it would be
> nice to have something like that to help delegate implementors.
>
> I suggest mentally evaluating the delegation points of URLSession with the
> perspective of the delegator (URLSession) being able to optimize what it
> does based what it delegate has provided and implementation for. For
> example the new metrics delegation point like could optimize away book
> keeping and related processing if the delegate isn't interested.
> Additionally look at it from the point of view of a delegate implementor
> noting the despite already having some number of sub-protocols you still
> often only implement one or two delegate points. Alternate swifty
> implementations likely exist that would be interesting to explore to help
> inform what makes sense as a language addition and/or help folks used to
> "traditional" delegation pattern under Objective-C follow more Swifty
> patterns going forward.
>
> -Shawn
>
> On Tue, Nov 15, 2016 at 9:24 AM Karl <razielim at gmail.com> wrote:
>
>
> On 15 Nov 2016, at 16:46, Shawn Erickson <shawnce at gmail.com> wrote:
>
> This has been discussed somewhat heavily in the past and nothing yet has
> really moved forward on it. I do think a good way of doing something like
> this would be helpful. I have resulted to defining an interface with an
> extension that provides empty defaults and for each function a match bool
> var exists to imply if it exists or not. The code accepting a delegate can
> probe these bool vars to configure itself to efficiently operate based on
> knowledge about what the delegate expects (some missing from most proposed
> solutions other then @objc optional).
> On Tue, Nov 15, 2016 at 6:59 AM Karl via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On 15 Nov 2016, at 12:22, Haravikk via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On 15 Nov 2016, at 07:53, Rick Mann via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On Nov 14, 2016, at 22:51 , Charlie Monroe via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> One major example is the NS/UITableViewDataSource or Delegate - there are
> many many methods that you don't need to implement, hence are optional.
>
> But I think that this was partially solved by default implementation of
> protocol methods, which pretty much does what you want...
>
>
> I just realized I only responded to someone else, and not the whole list.
> It does, but it forces me to make the return value of the protocol method
> optional, so that the default implementation can return nil.
>
> In the end, I guess that's not so bad, since I'm not happy with the entire
> approach, but it'll do for now.
>
>
> What's different about having the method return nil vs being optional?
> You're attempting to call it either way, and presumably need some means of
> handling the return value, except in Swift it's all nice and explicit and
> easy to put in a conditional like:
>
> if let result = myObject.someOptionalMethod() { /* Do some stuff */ }
> print(myObject.someOptionalStringMethod() ?? "")
>
> And so-on. If you need a method to be both optional, and return a nilable
> result then you can use a double optional like so:
>
> if let result = myObject.someDoubleOptionalMethod() { // Method was
> implemented
> if let value = result { // Method returned a value
> /* Do some stuff */
> }
> }
>
>
> By defining the methods as returning an Optional and throwing in default
> implementations you can specify fewer, bigger protocols and make clear what
> the requirements really are, though personally given the choice I'd prefer
> a dozen smaller protocols that are absolutely explicit in what they do.
>
> But yeah, I think the tools you need are all there already; maybe there's
> an argument to be made for allowing default return values on protocol
> methods, to reduce the boiler-plate?
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> I think there is a difference between:
>
> - A method which returns an optional result, and
> - An optional method which, if present, always returns a result
>
> Perhaps not so much of a difference at the usage site (it’s just a
> question of placing a ? for optional chaining), but semantically and when
> conforming to the protocol, they mean different things.
>
> - Karl
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> If you don’t mind me asking, what is your use-case?
>
> Even though I think "optional methods" and “methods returning optionals”
> are different things, I don’t really have any examples where optional
> methods are better than sub-protocols.
>
> e.g.
>
> ```
> // Core callbacks
> protocol MyDelegate { }
>
> // Optional callbacks, added like a mixin
> protocol MyDelegateWithExtras : MyDelegate { }
>
> // Some more optional callbacks
> protocol MySubDelegate : MyDelegate {}
>
> class DelegateImpl : MySubDelegate, MyDelegateWithExtras {
>   // Implement all core + optional callbacks
> }
>
> var d : MyDelegate = DelegateImpl()
>
> if let extras = d as? MyDelegateWithExtras {
>     // invoke optional functionality
> }
> ```
>
> I don’t know what the overhead of the as? call is, but it’s almost
> certainly less than an Obj-C `respondsToSelector` call. Depending on
> whether you need to swap the delegate for objects of different types, you
> could also use generics to optimise the checks (and possibly more) away.
>
> - Karl
>
>
>
> You sometimes needed those kind of caching techniques in Objective-C,
> because it’s such a dynamic language. The question of “does this object
> respond to this selector” has many complex considerations. For one thing,
> objects may add and remove methods (or have it done to them) at any time.
> Objects can even synthesise implementations the first time they receive a
> selector. It’s been optimised massively over the years, but it can still be
> a pretty slow operation -- and since hardly anything actually makes use of
> those features it’s common to ask once and cache the responses in a
> bitmask. In Objective-C, asking whether or not an object conforms to a
> protocol just cascades in to a bunch of calls to “respondsToSelector”, so
> it’s also very painful.
>
> The Swift runtime doesn’t have those dynamic features. If you added any
> methods to a bridged Swift object via the Obj-C runtime, those methods
> wouldn’t be callable from your Swift code anyway, so we never have to worry
> about that. Protocols in Swift are not the loose contracts of Objective-C;
> you can create empty “marker” protocols and different objects may or may
> not conform to it, even though it has no functional requirements. That
> means testing for conformance should be much faster, too (and covers all
> requirements at once).
>
> Protocol dispatch in Swift is fast, there is something called a “protocol
> witness table” (vtable + pointer + lifetime func ptrs), which is what is
> actually getting stored when you declare a variable with only a protocol
> for a type. So there isn’t really a huge runtime cost from the dispatch
> anymore either, and you don’t need to explicitly resolve and store the IMPs
> yourself to get decent performance.
>
> - Karl
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161116/56ccb262/attachment.html>


More information about the swift-evolution mailing list