[Proposal draft] Generalized Naming for Any Function


(Douglas Gregor) #1

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


(Brent Royal-Gordon) #2

the proposal follows, and is available here as well:

  https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md

This link doesn't work; in fact, you don't seem to have *any* public repositories.

···

--
Brent Royal-Gordon
Architechies


(Frederick Kellison-Linn) #3

Given that someView.insertSubview(_:at:) can be correctly parsed, I would strongly lean towards the no-backtick alternative mentioned at the end. I feel as though the backticks end up looking very cluttered (particularly when you get into the double-nested backticks), and it seems cleaner to be able to reference a method as it was declared rather than having to add extra syntax.

In reference to the issues noted with this approach:

IMO, there is already enough syntactic difference between getters/setters and normal methods to justify requiring a different syntax to reference them. For instance, the # syntax could be used so that, button.currentTitle.get would reference Optional<String>.get, and button.currentTitle#get would reference the getter. Or, button.`currentTitle.get` could reference the getter (i.e. backticks are only required in cases that are ambiguous).

I also think it is reasonable to require that in the case of a method with no arguments such as set.removeAllElements, the programmer be expected to know the difference between the expression with and without the trailing parenthesis. After all, that distinction already exists in the language, and would not disappear with this proposed addition. If a parallel syntax for referencing methods with no arguments is strongly desired, perhaps something such as set.removeAllElements(:), set#removeAllElements(), or similar could be used, though I think that the present system for referencing these methods is sufficient.

Are there other obvious reasons why this alternative wouldn’t work? I think it is the cleanest of the alternatives and avoids littering the code with backticks.

FKL

···

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

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


(Joe Groff) #4

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 <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:)`

This part seems reasonable to me.

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]) -> ()

At least as far as pure Swift is concerned, for unapplied access, like `UIButton.currentTitle`, I think it would be more consistent with the way method references works for that to give you the getter (or lens) without decoration. instance.instanceMethod has type Args -> Ret, and Type.instanceMethod has type Self -> Args -> Ret; by analogy, since instance.instanceProperty has type Ret or inout Ret, it's reasonable to expect Type.instanceProperty to have type Self -> [inout] Ret. Forming a getter or setter partially applied to an instance feels unmotivated to me—{ button.currentTitle } or { button.currentTitle = $0 } already work, and are arguably clearer than this syntax.

I acknowledge that this leaves forming selectors from setters out to dry, but I feel like that's something that could be incorporated into a "lens" design along with typed selectors. As a rough sketch, we could say that the representation of @convention(selector) T -> inout U is a pair of getter/setter selectors, and provide API on Selector to grab the individual selectors from that, maybe Selector(getterFor: UIView.currentTitle)/(setterFor: UIView.currentTitle). I don't think get/set is a good interface for working with Swift properties, so I don't like the idea of building in language support to codify it beyond what's needed for ObjC interaction.

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.

-Joe

···

On Dec 26, 2015, at 11:22 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:


(Joe Groff) #5

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?

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> 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 <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
https://lists.swift.org/mailman/listinfo/swift-evolution


(Bartlomiej Cichosz) #6

Hi,

I am sorry if this was already considered (jumping in a bit late), but what about using the following syntax:

let fn = aGameView.insertSubview(_, aboveSubview: _)

This is similar to a function calling syntax (rather than function definition syntax), but with _ instead of specific arguments.

The reason I think this may be useful is because it could be generalized to a syntax for partial application (assuming such functionality is desired in Swift):

let insertCardViewAtTheBottomOfTheDeck = aGameView.insertSubview(_, aboveSubview: playingSurfaceView)

then:

insertCardViewAtTheBottomOfTheDeck(anotherCard)

Or:

let insertMyCard = aGameView.insertSubview(myCard, aboveSubview: _)

then:

insertMyCard(aboveSubview:otherCard)

In the above examples, the definitions of insertCardViewAtTheBottomOfTheDeck and insertMyCard would return partially applied functions. Whereas the first example, the definition of fn, where all arguments are specified as _ is a special case that refers to the original function.

Some of the issues mentioned in the proposal remain, for example, how to disambiguate same function names with different parameter types, such as:

let fn1 = aGameView.insertSubview(_, aboveSubview: _:CardView)

or

let fn2 = aGameView.insertSubview(_, aboveSubview: _ as CardView)

Or different return values:

let fn3 = aGameView.insertSubview(_, aboveSubview: playingSurfaceView) -> Bool

Getters and setters, using the example from the proposal:

let getRow = someMatrix.subscript(row: _).get

All of the above assumes, of course, that presence of one or more _ is sufficient to parse these not as function calls, but partial application expressions (with the special case of all _s being just reference to the original function). If that’s the case, it would eliminate the need for back-ticks.

Regards,

Bart

···

On Dec 27, 2015, at 02:22, Douglas Gregor via swift-evolution <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

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 <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
https://lists.swift.org/mailman/listinfo/swift-evolution


(plx) #7

I like this proposal overall and the proposed syntax in particular; I think it addresses a real issue in a straightforward, predictable way.

As an aside — and FWIW — one thing I was at some point going to propose was a shorthand syntax for specifying trivial “argument-ordering-adjustment” closures.

EG: in the context of the proposal, a shorthand like this:

  let indicesForViews: [(Int,UIView)] = …
  indicesForViews.forEach(self.`insertSubview($1,at:$0)`)

…although using something other than back-ticks may be necessary to avoid ambiguity.

In the example above, it’s a bit contrived; in general, it’s never actually-shorter than the current option:

  let indicesForViews: [(Int,UIView)] = …
  indicesForViews.forEach({ self.insertSubview($1, at: $0) })

…but it would still make things more symmetric between the “function name” case and the inline-short-closure case.

More importantly, it’d allow a streamlined way to express things like this:

  // shorthand:
  let flippedArguments = self.`insertSubview($1, at: $0)`

  // current syntax:
  let flippedArguments = { (Int,UIView) -> Void in self.insertSubview($1, at: $0) }

…which will be a lot more useful once we have a reliable way to pull such functions into local variables.

I’m not requesting this be included in the below proposal, just hoping the final syntax selected here not somehow inadvertently prevent such a construct from ever being created.

Apologies if this has already come up in the discussion.

···

On Dec 27, 2015, at 1:22 AM, Douglas Gregor via swift-evolution <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

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 <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
https://lists.swift.org/mailman/listinfo/swift-evolution


(Douglas Gregor) #8

Ah, thanks. I’ve made the repository public.

  - Doug

···

On Dec 26, 2015, at 11:43 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

the proposal follows, and is available here as well:

  https://github.com/DougGregor/swift-evolution/blob/generalized-naming/proposals/0000-generalized-naming.md

This link doesn't work; in fact, you don't seem to have *any* public repositories.


(Nicky Gerritsen) #9

I have to agree with Frederick that the two-backticks example looks horrible ;-). I guess the # way worjs better in that case.

I’m not entirely sure about his second remark: if we require that references to functions without arguments are written without parenthesis, don’t we then have some inconsistency? i.e. functions without arguments are obj.func while functions with arguments are obj.func(_:y:). I’m not really in favor of this inconsistency. But I’m not really sure currently how we can easily solve this without creating more strange inconsistencies...

Regards,

Nicky

···

On 27 dec. 2015, at 09:27, Frederick Kellison-Linn via swift-evolution <swift-evolution@swift.org> wrote:

Given that someView.insertSubview(_:at:) can be correctly parsed, I would strongly lean towards the no-backtick alternative mentioned at the end. I feel as though the backticks end up looking very cluttered (particularly when you get into the double-nested backticks), and it seems cleaner to be able to reference a method as it was declared rather than having to add extra syntax.

In reference to the issues noted with this approach:

IMO, there is already enough syntactic difference between getters/setters and normal methods to justify requiring a different syntax to reference them. For instance, the # syntax could be used so that, button.currentTitle.get would reference Optional<String>.get, and button.currentTitle#get would reference the getter. Or, button.`currentTitle.get` could reference the getter (i.e. backticks are only required in cases that are ambiguous).

I also think it is reasonable to require that in the case of a method with no arguments such as set.removeAllElements, the programmer be expected to know the difference between the expression with and without the trailing parenthesis. After all, that distinction already exists in the language, and would not disappear with this proposed addition. If a parallel syntax for referencing methods with no arguments is strongly desired, perhaps something such as set.removeAllElements(:), set#removeAllElements(), or similar could be used, though I think that the present system for referencing these methods is sufficient.

Are there other obvious reasons why this alternative wouldn’t work? I think it is the cleanest of the alternatives and avoids littering the code with backticks.

FKL

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

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Joe Groff) #10

Some more things to consider:

- Our naming conventions encourage the first parameter to most methods to be unlabeled, so unlabeled parameters come up a lot. I don't think there's a grammatical requirement for an identifier before each colon; maybe we can leave out the underscore and use `foo(:bar:)` instead of `foo(_:bar:)` to refer to unlabeled arguments.

- How do labeled references interact with default and variadic arguments? If you have a func foo(x: Int = 0, y: String = 0), can you refer to foo(x:) and foo(y:) to apply some of the defaulted arguments, or only foo(x:y:)? Would foo(y:x:) also work?

-Joe

···

On Dec 27, 2015, at 10:37 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

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

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 <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:)`

This part seems reasonable to me.

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]) -> ()

At least as far as pure Swift is concerned, for unapplied access, like `UIButton.currentTitle`, I think it would be more consistent with the way method references works for that to give you the getter (or lens) without decoration. instance.instanceMethod has type Args -> Ret, and Type.instanceMethod has type Self -> Args -> Ret; by analogy, since instance.instanceProperty has type Ret or inout Ret, it's reasonable to expect Type.instanceProperty to have type Self -> [inout] Ret. Forming a getter or setter partially applied to an instance feels unmotivated to me—{ button.currentTitle } or { button.currentTitle = $0 } already work, and are arguably clearer than this syntax.

I acknowledge that this leaves forming selectors from setters out to dry, but I feel like that's something that could be incorporated into a "lens" design along with typed selectors. As a rough sketch, we could say that the representation of @convention(selector) T -> inout U is a pair of getter/setter selectors, and provide API on Selector to grab the individual selectors from that, maybe Selector(getterFor: UIView.currentTitle)/(setterFor: UIView.currentTitle). I don't think get/set is a good interface for working with Swift properties, so I don't like the idea of building in language support to codify it beyond what's needed for ObjC interaction.

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.

-Joe

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(John McCall) #11

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]) -> ()

At least as far as pure Swift is concerned, for unapplied access, like `UIButton.currentTitle`, I think it would be more consistent with the way method references works for that to give you the getter (or lens) without decoration. instance.instanceMethod has type Args -> Ret, and Type.instanceMethod has type Self -> Args -> Ret; by analogy, since instance.instanceProperty has type Ret or inout Ret, it's reasonable to expect Type.instanceProperty to have type Self -> [inout] Ret. Forming a getter or setter partially applied to an instance feels unmotivated to me—{ button.currentTitle } or { button.currentTitle = $0 } already work, and are arguably clearer than this syntax.

I acknowledge that this leaves forming selectors from setters out to dry, but I feel like that's something that could be incorporated into a "lens" design along with typed selectors. As a rough sketch, we could say that the representation of @convention(selector) T -> inout U is a pair of getter/setter selectors, and provide API on Selector to grab the individual selectors from that, maybe Selector(getterFor: UIView.currentTitle)/(setterFor: UIView.currentTitle). I don't think get/set is a good interface for working with Swift properties, so I don't like the idea of building in language support to codify it beyond what's needed for ObjC interaction.

I know this might be too early, but: what syntax are we thinking of for lenses? We might want to design this with future consistency in mind.

John.

···

On Dec 27, 2015, at 10:37 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.

-Joe

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #12

I’m a fan of good error recovery, but I don’t think it is a major concern here for two reasons:

1) The most common case in a method will lack a label, and "thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried reference.
2) A common case of accidentally completing a nullary call (thing.foo() vs thing.foo) will produce a type error. We already produce good QoI for an unapplied function - adding the inverse would be simple.

Further, it will be uncommon *in general* to form a curried reference, so error recovery doesn’t have to be perfect in all the edge cases. As with other commenters, if it is at all possible to avoid the extra backticks, I’d really prefer that.

-Chris

···

On Dec 27, 2015, at 10:37 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.


(Douglas Gregor) #13

Given that someView.insertSubview(_:at:) can be correctly parsed, I would strongly lean towards the no-backtick alternative mentioned at the end. I feel as though the backticks end up looking very cluttered (particularly when you get into the double-nested backticks), and it seems cleaner to be able to reference a method as it was declared rather than having to add extra syntax.

In reference to the issues noted with this approach:

IMO, there is already enough syntactic difference between getters/setters and normal methods to justify requiring a different syntax to reference them. For instance, the # syntax could be used so that, button.currentTitle.get would reference Optional<String>.get, and button.currentTitle#get would reference the getter. Or, button.`currentTitle.get` could reference the getter (i.e. backticks are only required in cases that are ambiguous).

I also think it is reasonable to require that in the case of a method with no arguments such as set.removeAllElements, the programmer be expected to know the difference between the expression with and without the trailing parenthesis. After all, that distinction already exists in the language, and would not disappear with this proposed addition. If a parallel syntax for referencing methods with no arguments is strongly desired, perhaps something such as set.removeAllElements(:), set#removeAllElements(), or similar could be used, though I think that the present system for referencing these methods is sufficient.

Are there other obvious reasons why this alternative wouldn’t work? I think it is the cleanest of the alternatives and avoids littering the code with backticks.

Not having the back-ticks means that you will need to use contextual type information to disambiguate the zero-parameter case from other cases. For example:

  class Foo {
    func doSomething() { }
    func doSomething(value: Int) { }
  }

  let fn = Foo.doSomething // ambiguous
  let fn2 = Foo.doSomething(_:slight_smile: // okay
  let fn3: (Foo) -> () -> Void = Foo.doSomething // okay
  let fn3: (Foo) -> (Int) -> Void = Foo.doSomething // okay

My general complaint with the “drop the backticks” approach is that it doesn’t solve the whole problem. Sure, it solves 95% of the problem with a little less syntax, but now you need to invent yet another mechanism to handle the other cases (#set, contextual type disambiguation, etc)… which seems inconsistent to me.

  - Doug

···

On Dec 27, 2015, at 12:27 AM, Frederick Kellison-Linn via swift-evolution <swift-evolution@swift.org> wrote:

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

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Douglas Gregor) #14

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!

···

Sent from my iPhone

On Dec 29, 2015, at 10:17 AM, Joe Groff <jgroff@apple.com> wrote:

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> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Douglas Gregor) #15

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

[snip]

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]) -> ()

At least as far as pure Swift is concerned, for unapplied access, like `UIButton.currentTitle`, I think it would be more consistent with the way method references works for that to give you the getter (or lens) without decoration. instance.instanceMethod has type Args -> Ret, and Type.instanceMethod has type Self -> Args -> Ret; by analogy, since instance.instanceProperty has type Ret or inout Ret, it's reasonable to expect Type.instanceProperty to have type Self -> [inout] Ret.

Yes, that seems reasonable.

Forming a getter or setter partially applied to an instance feels unmotivated to me—{ button.currentTitle } or { button.currentTitle = $0 } already work, and are arguably clearer than this syntax.

I’m not strongly motivated by it in and of itself; rather, I like the idea of being able to get at all of the functions (for completeness/consistency), partly because of the Objective-C selector issue.

I acknowledge that this leaves forming selectors from setters out to dry, but I feel like that's something that could be incorporated into a "lens" design along with typed selectors. As a rough sketch, we could say that the representation of @convention(selector) T -> inout U is a pair of getter/setter selectors,

I should weigh in over on a typed-selectors thread, but my personal view is that typed selectors are a well-designed feature that isn't worth doing: one would probably not use them outside of interoperability with Objective-C. To make that work, we'd need a Clang feature as well (to express the types), then all of the relevant Objective-C APIs would need to adopt it for us to see the benefits. On iOS, we are talking about a relatively small number of APIs (100-ish), and many of those have blocks/closure-based variants that are preferred.

and provide API on Selector to grab the individual selectors from that, maybe Selector(getterFor: UIView.currentTitle)/(setterFor: UIView.currentTitle)

Sure. I suspect that retrieving the selector of a getter/setter will be fairly rare, so I'm fine with that operation being ugly.

. I don't think get/set is a good interface for working with Swift properties, so I don't like the idea of building in language support to codify it beyond what's needed for ObjC interaction.

That is an excellent point. I think you've convinced me to drop the getter/setter part of this: lenses are the right abstraction for working with properties, and we can handle ObjC getter/setter in some other way.

···

On Dec 27, 2015, at 10:37 AM, Joe Groff <jgroff@apple.com> wrote:
On Dec 26, 2015, at 11:22 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.

-Joe


(Matthew Johnson) #16

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?

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`()
  }
}

Like many others I am not a fan of the backticks being required in common use cases, but I don’t mind them in edge cases at all. In those cases they are far better than no solution. So +1 to using backticks to allow disambiguation!

···

On Dec 29, 2015, at 12:17 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

-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

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(John McCall) #17

The concern, I think, is that a messed-up normal call might look like a curried reference.

My inclination would be to go the other way: if we get a syntax for this that we like, I think we should use it for *all* curried member references, and reject things like foo.bar in favor of foo.`bar`. The ability to write foo.bar for a method has always struck me as more clever than wise, to be honest.

John.

···

On Dec 27, 2015, at 4:02 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Dec 27, 2015, at 10:37 AM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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?

From what I remember, the bigger concern with allowing foo(bar:bas:) without backticks is parser error recovery. The unambiguity with call syntax depends on having the `:)` token pair at the end. The edit distance between foo(bar:bas:) and a call foo(bar: bas) or work-in-progress call foo(bar: x, bas: ) is pretty slight, and would be tricky to give good diagnostics for. If we felt confident we could give good diagnostics, I'd support removing the backticks.

I’m a fan of good error recovery, but I don’t think it is a major concern here for two reasons:

1) The most common case in a method will lack a label, and "thing.foo(_: “ and “thing.foo(:” are both unambiguously a curried reference.
2) A common case of accidentally completing a nullary call (thing.foo() vs thing.foo) will produce a type error. We already produce good QoI for an unapplied function - adding the inverse would be simple.

Further, it will be uncommon *in general* to form a curried reference, so error recovery doesn’t have to be perfect in all the edge cases. As with other commenters, if it is at all possible to avoid the extra backticks, I’d really prefer that.


(Frederick Kellison-Linn) #18

Commentary inline below.

FKL

Given that someView.insertSubview(_:at:) can be correctly parsed, I would strongly lean towards the no-backtick alternative mentioned at the end. I feel as though the backticks end up looking very cluttered (particularly when you get into the double-nested backticks), and it seems cleaner to be able to reference a method as it was declared rather than having to add extra syntax.

In reference to the issues noted with this approach:

IMO, there is already enough syntactic difference between getters/setters and normal methods to justify requiring a different syntax to reference them. For instance, the # syntax could be used so that, button.currentTitle.get would reference Optional<String>.get, and button.currentTitle#get would reference the getter. Or, button.`currentTitle.get` could reference the getter (i.e. backticks are only required in cases that are ambiguous).

I also think it is reasonable to require that in the case of a method with no arguments such as set.removeAllElements, the programmer be expected to know the difference between the expression with and without the trailing parenthesis. After all, that distinction already exists in the language, and would not disappear with this proposed addition. If a parallel syntax for referencing methods with no arguments is strongly desired, perhaps something such as set.removeAllElements(:), set#removeAllElements(), or similar could be used, though I think that the present system for referencing these methods is sufficient.

Are there other obvious reasons why this alternative wouldn’t work? I think it is the cleanest of the alternatives and avoids littering the code with backticks.

Not having the back-ticks means that you will need to use contextual type information to disambiguate the zero-parameter case from other cases. For example:

  class Foo {
    func doSomething() { }
    func doSomething(value: Int) { }
  }

  let fn = Foo.doSomething // ambiguous
  let fn2 = Foo.doSomething(_:slight_smile: // okay
  let fn3: (Foo) -> () -> Void = Foo.doSomething // okay
  let fn3: (Foo) -> (Int) -> Void = Foo.doSomething // okay

Why does Foo.doSomething have to be ambiguous? I would say that if this system is implemented (especially if without backticks), Foo.doSomething should only be able to refer to the no-argument overload of doSomething (i.e. "let fn3: (Foo) -> (Int) -> Void = Foo.doSomething" would be an error). This would break existing code that relies on the type disambiguation, but we would be able to offer a replacement for it.

My general complaint with the “drop the backticks” approach is that it doesn’t solve the whole problem. Sure, it solves 95% of the problem with a little less syntax, but now you need to invent yet another mechanism to handle the other cases (#set, contextual type disambiguation, etc)… which seems inconsistent to me.

I feel as though backticks are the inconsistent approach in this case, especially because they already have one meaning in Swift that is used in the same context (as Chris notes). The 'natural' solution to me would be to refer to method references by writing them like a call without arguments, just like the name of a selector in Objective C.

Backticks also have the unfortunate properties of being relatively unknown characters to those who may not have a lot of programming experience, and at first glance are hard to differentiate from single quotes. In the context of using keywords as identifiers, I don't see those to be as big of issues, because except in very specific cases the easier solution is simply "come up with a different name for your identifier". To have to use backticks whenever a method reference is desired is, IMO, confusing and cluttered syntax.

I think that the best solution is to extend the current syntax as naturally as possible, and only introduce the backticks (or other syntax) as needed in cases such as obj.`property.get` (or obj.property#get). Obviously my notion of 'natural' is going to differ from others', but I think that most would agree that being able to write "Foo.doSomething(_:bar:)" is a more intuitive extension of the syntax than "Foo.`doSomething(_:bar:)`.

···

On Dec 27, 2015, at 8:40 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Dec 27, 2015, at 12:27 AM, Frederick Kellison-Linn via swift-evolution <swift-evolution@swift.org> wrote:

  - Doug

On Dec 26, 2015, at 11:22 PM, Douglas Gregor via swift-evolution <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

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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(TJ Usiyan) #19

Do things get any better if we combine the proposed changes and remove the
bare case? Begin function reference with some symbol (# here but it doesn't
matter), only use back tics to disambiguate keywords (which lines up with
their current use) and remove the unadorned case to avoid ambiguity.

class Foo {
func doSomething() { }
func doSomething(value: Int) { }
func sub
}

let fn = Foo#doSomething // no longer allowed
let fn = Foo#doSomething() // okay
let fn2 = Foo#doSomething(_:) // okay

// and

let getRow = someMatrix#`subscript`(row:).get

···

On Sun, Dec 27, 2015 at 10:40 PM, Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

On Dec 27, 2015, at 12:27 AM, Frederick Kellison-Linn via swift-evolution < > swift-evolution@swift.org> wrote:

Given that someView.insertSubview(_:at:) can be correctly parsed, I would
strongly lean towards the no-backtick alternative mentioned at the end. I
feel as though the backticks end up looking very cluttered (particularly
when you get into the double-nested backticks), and it seems cleaner to be
able to reference a method as it was declared rather than having to add
extra syntax.

In reference to the issues noted with this approach:

IMO, there is already enough syntactic difference between getters/setters
and normal methods to justify requiring a different syntax to reference
them. For instance, the # syntax could be used so that,
button.currentTitle.get would reference Optional<String>.get, and
button.currentTitle#get would reference the getter. Or,
button.`currentTitle.get` could reference the getter (i.e. backticks are
only required in cases that are ambiguous).

I also think it is reasonable to require that in the case of a method with
no arguments such as set.removeAllElements, the programmer be expected to
know the difference between the expression with and without the trailing
parenthesis. After all, that distinction already exists in the language,
and would not disappear with this proposed addition. If a parallel syntax
for referencing methods with no arguments is strongly desired, perhaps
something such as set.removeAllElements(:), set#removeAllElements(), or
similar could be used, though I think that the present system for
referencing these methods is sufficient.

Are there other obvious reasons why this alternative wouldn’t work? I
think it is the cleanest of the alternatives and avoids littering the code
with backticks.

Not having the back-ticks means that you will need to use contextual type
information to disambiguate the zero-parameter case from other cases. For
example:

class Foo {
func doSomething() { }
func doSomething(value: Int) { }
}

let fn = Foo.doSomething // ambiguous
let fn2 = Foo.doSomething(_:slight_smile: // okay
let fn3: (Foo) -> () -> Void = Foo.doSomething // okay
let fn3: (Foo) -> (Int) -> Void = Foo.doSomething // okay

My general complaint with the “drop the backticks” approach is that it
doesn’t solve the whole problem. Sure, it solves 95% of the problem with a
little less syntax, but now you need to invent yet another mechanism to
handle the other cases (#set, contextual type disambiguation, etc)… which
seems inconsistent to me.

- Doug

On Dec 26, 2015, at 11:22 PM, Douglas Gregor via swift-evolution < > 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

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
   <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
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#20

Any reason not to put in a proposal to change this everywhere, e.g., diagnostics?

Stephen

···

On Dec 27, 2015, at 3:32 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

Some more things to consider:

- Our naming conventions encourage the first parameter to most methods to be unlabeled, so unlabeled parameters come up a lot. I don't think there's a grammatical requirement for an identifier before each colon; maybe we can leave out the underscore and use `foo(:bar:)` instead of `foo(_:bar:)` to refer to unlabeled arguments.