> On Dec 29, 2015, at 12:17 PM, Joe Groff via swift-evolution > <swift-evolution@swift.org> 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? > > 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`() > } > } >
Like many others I am not a fan of the backticks being required in common use cases, but I don’t mind them in edge cases at all. In those cases they are far better than no solution. So +1 to using backticks to allow disambiguation! > -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 > > > _______________________________________________ > 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