Sent from my iPhone
> On Dec 29, 2015, at 11:48 AM, Félix Cloutier <[email protected]> wrote: > > Currently, they can be disambiguated using (self as ProtocolA).bar(), no? Not if ProtocolA has self requirements or associated types. > > Félix > >> Le 29 déc. 2015 à 14:10:51, Erica Sadun via swift-evolution >> <[email protected]> a écrit : >> >> 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 >>> <[email protected]> wrote: >>> >>> >>> >>> Sent from my iPhone >>> >>>> On Dec 29, 2015, at 10:17 AM, Joe Groff <[email protected]> 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 >>>>> <[email protected]> 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 >>>>> >>>>> the proposal follows, and is available here as well: >>>>> >>>>> >>>>> https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md >>>>> >>>>> Comments appreciated! >>>>> >>>>> Generalized Naming for Any Function >>>>> >>>>> Proposal: SE-NNNN >>>>> Author(s): Doug Gregor >>>>> Status: Awaiting Review >>>>> Review manager: TBD >>>>> 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, continued here. See the Alternatives considered >>>>> section for commentary on that discussion. >>>>> >>>>> 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. >>>>> >>>>> 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: >>>>> 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. >>>>> >>>>> Alternatives considered >>>>> >>>>> Michael Henson proposed 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. 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 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 >>>>> [email protected] >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
