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 <[email protected]> wrote: > > On 15 Nov 2016, at 19:38, Shawn Erickson <[email protected]> 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 <[email protected]> wrote: > > > On 15 Nov 2016, at 16:46, Shawn Erickson <[email protected]> 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 < > [email protected]> wrote: > > > On 15 Nov 2016, at 12:22, Haravikk via swift-evolution < > [email protected]> wrote: > > > On 15 Nov 2016, at 07:53, Rick Mann via swift-evolution < > [email protected]> wrote: > > > On Nov 14, 2016, at 22:51 , Charlie Monroe via swift-evolution < > [email protected]> 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 > [email protected] > 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 > [email protected] > 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 >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
