> On Dec 29, 2015, at 12:03 PM, Douglas Gregor <dgre...@apple.com> wrote:
> 
> 
> 
> Sent from my iPhone
> 
> On Dec 29, 2015, at 11:03 AM, Douglas Gregor via swift-evolution 
> <swift-evolution@swift.org <mailto: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!
> 
> It does introduce some ambiguities at the margins. Given
> 
>   foo.`bar.get`()
> 
> Do we look for bar in the lexical scope or in the member scope of foo? Or 
> both with yet another disambiguation mechanism?
> 
> I'm still traumatized by implementing the related C++ rules for
> 
>   foo.bar::get 
> 
> :)

Clearly we should just adopt Koenig lookup rules.

> This is the other thing that nudges me toward dropping getters/setters from 
> the generalized naming proposal, because it leaves the use of '.' within 
> backticks for your newly-proposed meaning. 

Well, even if we drop `.get`/`.set` from the proposal, there's still the 
potential ambiguity between module names and type or protocol names. As an 
example from the wild, there's an Either module which defines an Either type, 
and we have bugs on file saying you can't pick one or the other. It seems like 
we'll ultimately want some sort of absolute qualification scheme.

-Joe

>>> 
>>> 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 <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

Reply via email to