[swift-evolution] [Proposal draft #2] Naming Functions with Argument Labels

Douglas Gregor dgregor at apple.com
Mon Jan 11 13:03:27 CST 2016

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


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

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.


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]

primary-expression -> unqualified-name generic-argument-clause[opt]

unqualified-name -> identifier
                  | identifier '(' ((identifier | '_') ':')+ ')'
Within the parentheses, the use of "+" is important, because it disambiguates:

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/b1e459ac/attachment.html>

More information about the swift-evolution mailing list