Talk about things you didn't know you needed until you see them. This is a really nice way of disambiguating!
-- E > On Dec 29, 2015, at 12:03 PM, Douglas Gregor via swift-evolution > <swift-evolution@swift.org> wrote: > > > > Sent from my iPhone > > On Dec 29, 2015, at 10:17 AM, Joe Groff <jgr...@apple.com > <mailto:jgr...@apple.com>> wrote: > >> We also have a problem with disambiguating same-named members that come from >> different extensions, whether via protocol extensions or independent >> concrete extensions from different modules. Could we extend this scheme to >> allow for disambiguating extension methods by protocol/module name? > > That's a fantastic idea! > >> >> extension ProtocolA { func foo() } >> extension ProtocolB { func foo() } >> >> public struct Foo: ProtocolA, ProtocolB { >> func callBothFoos() { >> self.`ProtocolA.foo`() >> self.`ProtocolB.foo`() >> } >> } >> >> import A // extends Bar with bar() >> import B // also extends Bar with bar() >> >> extension Bar { >> func callBothBars() { >> self.`A.bar`() >> self.`B.bar`() >> } >> } >> >> -Joe >> >>> On Dec 26, 2015, at 11:22 PM, Douglas Gregor via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> Hi all, >>> >>> Here’s a proposal draft to allow one to name any function in Swift. In >>> effect, it’s continuing the discussion of retrieving getters and setters as >>> functions started by Michael Henson here: >>> >>> >>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002168.html >>> >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002168.html> >>> >>> the proposal follows, and is available here as well: >>> >>> >>> https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md> >>> >>> Comments appreciated! >>> >>> Generalized Naming for Any Function >>> >>> Proposal: SE-NNNN >>> <https://github.com/apple/swift-evolution/blob/master/proposals/0000-generalized-naming.md> >>> Author(s): Doug Gregor <https://github.com/DougGregor> >>> Status: Awaiting Review >>> Review manager: TBD >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#introduction>Introduction >>> >>> Swift includes support for first-class functions, such that any function >>> (or method) can be placed into a value of function type. However, it is not >>> possible to specifically name every function that is part of a Swift >>> program---one cannot provide the argument labels when naming a function, >>> nor are property and subscript getters and setters referenceable. This >>> proposal introduces a general syntax that allows one to name anything that >>> is a function within Swift in an extensible manner. >>> >>> Swift-evolution thread: Michael Henson started a thread about the >>> getter/setter issue here >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002168.html>, >>> continued here >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002203.html>. >>> See the Alternatives considered >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#alternatives-considered> >>> section for commentary on that discussion. >>> >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#motivation>Motivation >>> >>> It's fairly common in Swift for multiple functions or methods to have the >>> same "base name", but be distinguished by parameter labels. For example, >>> UIView has three methods with the same base name insertSubview: >>> >>> extension UIView { >>> func insertSubview(view: UIView, at index: Int) >>> func insertSubview(view: UIView, aboveSubview siblingSubview: UIView) >>> func insertSubview(view: UIView, belowSubview siblingSubview: UIView) >>> } >>> When calling these methods, the argument labels distinguish the different >>> methods, e.g., >>> >>> someView.insertSubview(view, at: 3) >>> someView.insertSubview(view, aboveSubview: otherView) >>> someView.insertSubview(view, belowSubview: otherView) >>> However, when referencing the function to create a function value, one >>> cannot provide the labels: >>> >>> let fn = someView.insertSubview // ambiguous: could be any of the three >>> methods >>> In some cases, it is possible to use type annotations to disambiguate: >>> >>> let fn: (UIView, Int) = someView.insertSubview // ok: uses >>> insertSubview(_:at:) >>> let fn: (UIView, UIView) = someView.insertSubview // error: still ambiguous! >>> To resolve the latter case, one must fall back to creating a closure: >>> >>> let fn: (UIView, UIView) = { view, otherView in >>> button.insertSubview(view, otherView) >>> } >>> which is painfully tedious. A similar workaround is required to produce a >>> function value for a getter of a property, e.g., >>> >>> extension UIButton { >>> var currentTitle: String? { ... } >>> } >>> >>> var fn: () -> String? = { () in >>> return button.currentTitle >>> } >>> One additional bit of motivation: Swift should probably get some way to ask >>> for the Objective-C selector for a given method (rather than writing a >>> string literal). The argument to such an operation would likely be a >>> reference to a method, which would benefit from being able to name any >>> method, including getters and setters. >>> >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#proposed-solution>Proposed >>> solution >>> >>> Swift currently has a back-tick escaping syntax that lets one use keywords >>> for names, which would otherwise fail to parse. For example, >>> >>> func `try`() -> Bool { ... } >>> declares a function named try, even though try is a keyword. I propose to >>> extend the back-tick syntax to allow compound Swift names (e.g., >>> insertSubview(_:aboveSubview:)) and references to the accessors of >>> properties (e.g., the getter for currentTitle). Specifically, >>> >>> Compound names can be written entirely within the back-ticks, e.g., >>> >>> let fn = someView.`insertSubview(_:at:)` >>> let fn1 = someView.`insertSubview(_:aboveSubview:)` >>> The same syntax can also refer to initializers, e.g., >>> >>> let buttonFactory = UIButton.`init(type:)` >>> Getters and setters can be written using dotted syntax within the >>> back-ticks: >>> >>> let specificTitle = button.`currentTitle.get` // has type () -> String? >>> let otherTitle = UIButton.`currentTitle.get` // has type (UIButton) -> () >>> -> String? >>> let setTintColor = button.`tintColor.set` // has type (UIColor!) -> () >>> The same syntax works with subscript getters and setters as well, using the >>> full name of the subscript: >>> >>> extension Matrix { >>> subscript (row row: Int) -> [Double] { >>> get { ... } >>> set { ... } >>> } >>> } >>> >>> let getRow = someMatrix.`subscript(row:).get` // has type (Int) -> () -> >>> [Double] >>> let setRow = someMatrix.`subscript(row:).set` // has type (Int) -> >>> ([Double]) -> () >>> If we introduce property behaviors into Swift, the back-tick syntax could >>> also be used to refer to behaviors, e.g., accessing the lazy behavior of a >>> property: >>> >>> self.`myProperty.lazy`.clear() >>> Base names that are meaningful keywords (init and subscript) can be escaped >>> with a nested pair of back-ticks: >>> >>> extension Font { >>> func `subscript`() -> Font { >>> // return the subscript version of the given font >>> } >>> } >>> >>> let getSubscript = font.``subscript`()` // has type () -> Font >>> The "produce the Objective-C selector for the given method" operation will >>> be the subject of a separate proposal. However, here is one possibility >>> that illustrations how it uses the proposed syntax here: >>> >>> let getter: Selector = objc_selector(NSDictionary.`subscript(_:).get`) // >>> produces objectForKeyedSubscript: >>> let setter: Selector = objc_selector(NSDictionary.`subscript(_:).set`) // >>> produces setObject:forKeyedSubscript: >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#impact-on-existing-code>Impact >>> on existing code >>> >>> This is a purely additive feature that has no impact on existing code. The >>> syntactic space it uses is already present, and it merely extends the use >>> of back-ticks from storing a single identifier to more complex names. >>> >>> >>> <https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md#alternatives-considered>Alternatives >>> considered >>> >>> Michael Henson proposed >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002168.html> >>> naming getters and setters using # syntax followed by get or set, e.g., >>> >>> let specificTitle = button.currentTitle#get >>> The use of postfix # is a reasonable alternative here, and more lightweight >>> than two back-ticks for the simple getter/setter case. The notion could be >>> extended to allow argument labels for functions, discussed here >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002210.html>. >>> The proposals in that discussion actually included type annotations as >>> well, but the syntax seems cleaner---and more directly focused on >>> names---without them, e.g.,: >>> >>> let fn = someView.insertSubview#(_:at:) >>> which works. I didn't go with this syntax because (1) it breaks up Swift >>> method names such as insertSubview(_:at:)with an # in the middle, and (2) >>> while useful, this feature doesn't seem important enough to justify >>> overloading #further. >>> >>> Joe Groff notes >>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003008.html> >>> that lenses are a better solution than manually retrieving getter/setter >>> functions when the intent is to actually operate on the properties. That >>> weakens the case this proposal makes for making getters/setters available >>> as functions. However, it doesn't address the general naming issue or the >>> desire to retrieve the Objective-C selector for a getter/setter. >>> >>> Can we drop the back-ticks? It's very tempting to want to drop the >>> back-ticks entirely, because something like >>> >>> let fn = someView.insertSubview(_:at:) >>> can be correctly parsed as a reference to insertSubview(_:at:). However, it >>> breaks down at the margins, e.g., with getter/setter references or >>> no-argument functions: >>> >>> extension Optional { >>> func get() -> T { return self! } >>> } >>> >>> let fn1 = button.currentTitle.get // getter or Optional<String>.get? >>> let fn2 = set.removeAllElements() // call or reference? >>> >>> >>> - Doug >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution