On Mon, Jan 11, 2016 at 2:03 PM, Douglas Gregor via swift-evolution < swift-evolution@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
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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution