<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Dec 4, 2015, at 2:31 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 4, 2015, at 2:26 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline">On Dec 4, 2015, at 2:22 PM, Michel Fortin <<a href="mailto:michel.fortin@michelf.ca" class="">michel.fortin@michelf.ca</a>> wrote:<br class=""><br class="">Currently in Swift you can get a closure by referring to a method:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x = NSString.hasPrefix<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// x is of type NSString -> String -> Bool<br class=""><br class="">Something that would be useful here is if the closure created from Objective-C methods were special in that they could implicitly be converted to a Selector. Instead of writing manually a selector as a string, you'd just have to refer to the method, and you know there's no typo (or else you get a compile-time error). For instance, adding an observer to a NSNotificationCenter would work like this:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>notificationCenter.addObserver(self, selector: MyClass.observeNotification, name: NSSomeNotificationName, object: nil)<span class="Apple-converted-space"> </span><br class=""><br class="">This, making sure the correct selector is used for the designated method, seem like it should be somewhat more important in Swift 3 if it includes Evolution Proposal 0005 that suggests many Objective-C methods will be given Swift-specific names.<br class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md</a><br class=""><br class="">But why stop there when you can go one step further and actually improve type-safety? Instead of taking a Selector parameter, the NSNotificationCenter.addObserver method above could request a @convention(selector) closure of this form:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>@convention(selector) AnyObject -> NSNotification -> Void<br class=""><br class="">Under the hood that closure is still a plain selector pointer, but the compiler attaches proper type information to the arguments. Since `addObserver` now declares it wants a selector with the given signature, the compiler can enforce that the arguments and return type for the passed selector are compatible. You<span class="Apple-converted-space"> </span><br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">This is a great approach, and it's mostly exactly what I've had in mind for this. Another nice thing about @convention(selector) is that the compiler could also context-free closures, like with @convention(c), by compiling them down to categories with mangled methods.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="">Moreover, the @convention(selector) closure you get can then be used as a normal closure inside a Swift method that can be called from Objective-C:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>@objc func callSelector(selector: @convention(selector) NSString -> String -> Bool) -> Bool {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>let str = NSString(string: "hello")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>return selector(str)("hell")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x = NSString.hasPrefix<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// x is of type @convention(selector) NSString -> String -> Bool<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>callSelector(x)<br class=""><br class="">So that would make selectors less error-prone because the compiler can type-check them, and you can use selectors in Swift code in a very natural manner.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I would say that 'let x = NSString.hasPrefix' should still give you a @convention(swift) function value by default; that's what we do with method references in general, but you could ask for a @convention(selector) reference explicitly:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">let x: @convention(selector) X -> Y -> Z = X.hasPrefix</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote></div><br class=""><div class="">One wrinkle you need to consider is the different ARC behavior of method families. @convention(selector) would have to be restricted to referencing methods that don't belong to an usual method family or have unusual ownership rules, or else we'd need multiple @convention(init_selector), (copy_selector), (alloc_selector) etc. conventions.</div></div></div></blockquote><div><br class=""></div></div>Or, alternatively, encode that information in the type, which would be necessary for full ObjC fidelity anyway, since ObjC ARC allows you to override conventions with attributes.<div class=""><br class=""></div><div class="">The flip side is that, of course, that’s quite a bit more complicated.<br class=""><div class=""><br class=""></div><div class="">John.</div></div></body></html>