Swift regret: subscript argument label rules— Jordan Rose (@UINT_MIN) September 15, 2021
I bet a lot of people don’t know how flexible subscripts are in Swift. The reason they’re declared with function-like syntax is because the index part really is a parameter list. You can have labels. Multiple params. *0* params, even.
Part of the Swift Regrets series.
I bet a lot of people don’t know how flexible subscripts are in Swift. The reason they’re declared with function—like syntax is because the index part really is a parameter list. You can have labels. Multiple params. Zero params, even. But if you want labels, you have to say so explicitly:
subscript(at path: String)
even if the label is the same as the argument name:
subscript(path path: String)
which is different from function and initializer arguments. Why are subscripts different in this way?
Well, back before Swift 3, all three types of argument lists were different:
- Initializers had all arguments labeled by default.
- Functions had all arguments except the first labeled by default.
- Subscripts had no arguments labeled by default.
This matched the most common way each member showed up in APIs imported from Objective-C: init methods with the selector parts mapped to argument labels; regular methods with the first selector piece serving as the base name; and single-argument unlabeled subscripts.
But the rule for functions felt weird, and that was exacerbated when Swift’s current preposition-heavy naming conventions were settled on in Swift 3. Even imported methods had first-arg labels now. So functions changed to match initializers in SE-0046. And subscripts…were not changed. The most common subscripts by far are still unlabeled single-argument ones. But you also use members a lot more than you write them, and consistency across all three members with argument lists would have been better, in my opinion.