- Pitch: Getter-setter functions

For some functions, it makes sense to both get the value from the function, and set a value to the function. Here are a few examples.

UIButton.title(for: UIControl.State) -> String?
UIButton.setTitle(_ title: String?, for: UIControl.State)
UIButton.color(for: UIControl.State) -> UIColor?
UIButton.setColor(_ color: UIColor?, for: UIControl.State)
NSObject.value(forKey: String) -> Any?
NSObject.setValue(_ value: Any?, forKey: String)

With getter-setter functions, these could be simplified and be easier to use.

UIButton.title(for state: UIControl.State) -> String? { get set }
UIButton.color(for state: UIControl.State) -> UIColor? { get set }
NSObject.value(forKey: String) -> Any? { get set }

Do I understand correctly that you are proposing to allow code such as:

button.title(for: someState)? += "!"

Yes, you can use subscripts for that:

button[titleFor: state] = ...
... = button[titleFor: state]
button[titleFor: state, default: ""] += "!"

Note that since quite some time, getters (to get the state of UI elements) are considered bad style as this leads to UI elements being the source of truth, which is odd and often leads to a situation when you have multiple conflicting sources of truth with results into wrong UI state; we had this trend since very first version of watchOS, then SwiftUI obviously.

It's worth adding that there's indeed this disparity of functions being get-only and named only and subscripts being unnamed only. If we align the two (to have the ability for functions to be get/set and potentially unnamed, and to have the ability for subscripts to be named) – then the line between functions and subscripts is blurred to the point we could even get rid of subscripts. Was this pitched already?


No, just discussed here and there since 2014. E.g. Parameterized Properties or Named Subscripts - #6 by anon9791410

The lack of named subscripts has always been a problem. Although they weren't taken out of the language, callAsFunction made get-only subscripts redundant. Settable parenthesis syntax would make settable ones redundant as well, except!

You cannot get rid of static subscripts, because that's the same syntax that initializers use. You could totally get rid of [] for instance members though.

1 Like

Speaking of which, wouldn't it be more logical to not have the callAsFunction name, just do how we did it with subscripts?

    func(param: Int) { ... }
    // similar to `subscript(param: Int) { ... }`
    // same as `func callAsFunction(param: Int) { ... }`