[swift-evolution] [Proposal draft #2] Naming Functions with Argument Labels
Douglas Gregor
dgregor at apple.com
Mon Jan 11 15:18:33 CST 2016
> On Jan 11, 2016, at 12:49 PM, Joe Groff <jgroff at apple.com> wrote:
>
> SGTM. A few points I didn't see addressed from the last thread:
>
> - Do we need the '_' representing unlabeled arguments? 'foo(:bar:)' should be workable, as in ObjC.
We discussed this a looooong while back and decided that we wanted the ‘_’ to emphasize that there is an argument there. The difference between “foo(:bar:)” and “foo(bar:)” is barely visible.
> - How do references to defaulted or variadic arguments work? Do you have to reference their labels completely in declared order, or could you refer to 'func foo(x: Int = 5, y: String = "")' as 'foo(y:x:)', 'foo(x:)', and/or 'foo(y:)' as well?
You have to reference their labels completely in declared order; that’s the name of the method.
- Doug
>
> -Joe
>
>> On Jan 11, 2016, at 11:03 AM, Douglas Gregor via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>> Hi all,
>>
>> I’ve updated and simplified my “Generalized Naming for Any Function” proposal to only deal with naming functions with argument labels, and dropping the back-ticks. Comments welcome! Proposal is here
>>
>> 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>
>>
>> and inline:
>>
>> Naming Functions with Argument Labels
>>
>> 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/tree/generalized-naming#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, when specifying the name of a function, one can only provide the base name, (e.g., insertSubview) without the argument labels. For overloaded functions, this means that one must disambiguate based on type information, which is awkward and verbose. This proposal allwos one
>>
>> 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: The first draft of this proposal was discussed here <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004555.html>. It included support for naming getters/setters (separately brought up by Michael Henson 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>). Joe Groff convinced <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004579.html> me that lenses are a better approach for working with getters/setters, so I've dropped them from this version of the proposal.
>>
>> <https://github.com/DougGregor/swift-evolution/tree/generalized-naming#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, aboveSubview: otherView)
>> }
>> which is painfully tedious.
>>
>> 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/tree/generalized-naming#proposed-solution>Proposed solution
>>
>> I propose to extend function naming to allow compound Swift names (e.g., insertSubview(_:aboveSubview:)) anywhere a name can occur. Specifically,
>>
>> 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:)
>> 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(NSDictionary.insertSubview(_:aboveSubview:)) // produces insertSubview:aboveSubview:.
>> <https://github.com/DougGregor/swift-evolution/tree/generalized-naming#detailed-design>Detailed Design
>>
>> Grammatically, the primary-expression grammar will change from:
>>
>> primary-expression -> identifier generic-argument-clause[opt]
>> to:
>>
>> primary-expression -> unqualified-name generic-argument-clause[opt]
>>
>> unqualified-name -> identifier
>> | identifier '(' ((identifier | '_') ':')+ ')'
>> Within the parentheses, the use of "+" is important, because it disambiguates:
>>
>> f()
>> as a call to f rather than a reference to an f with no arguments. Zero-argument function references will still require disambiguation via contextual type information.
>>
>> <https://github.com/DougGregor/swift-evolution/tree/generalized-naming#impact-on-existing-code>Impact on existing code
>>
>> This is a purely additive feature that has no impact on existing code.
>>
>> <https://github.com/DougGregor/swift-evolution/tree/generalized-naming#alternatives-considered>Alternatives considered
>>
>> 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.
>>
>> Bartlomiej Cichosz suggests <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004739.html> a general partial application syntax using _ as a placeholder, e.g.,
>>
>> aGameView.insertSubview(_, aboveSubview: playingSurfaceView)
>> When all arguments are _, this provides the ability to name any method:
>>
>> aGameView.insertSubview(_, aboveSubview: _)
>> I decided not to go with this because I don't believe we need such a general partial application syntax in Swift. Closures using the $ names are nearly as concise, and eliminate any questions about how the _ placeholder maps to an argument of the partially-applied function:
>>
>> { aGameView.insertSubview($0, aboveSubview: playingSurfaceView) }
>>
>>
>>
>>
>> - Doug
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/eba8999c/attachment.html>
More information about the swift-evolution
mailing list