Intuition behind the Swift external/local parameter system
By: . Published: . Categories: swift.David Bryant Copeland picks out Swift’s external/local parameter system as something never before seen:
The notion of giving named parameters different names for the caller than are used in the implementation is not something I’ve seen before, and it’s kinda genius.
But further reflection convinced me that allowing different external and local parameter names is simply the Swift version of a common Objective-C practice.
External and Local Parameters in Obj-C
Consider these parallel Obj-C and Swift method declarations:
- (void)insertPerson:(Person *const)p atIndex:(const NSUInteger)i;
func insert(person p: Person, index i: Int)
The Obj-C version demonstrates “external” parameter names in the form of a verbose selector. In Swift, the selector components move into the parens as external parameter names.
The Obj-C formal parameter names are analogous to the local parameter names in Swift.
The Swift external-then-local declaration order perfectly follows the Obj-C
selector-chunk-then-argument order:
Swift person p: Person
vs. Obj-C Person:(Person *const)p
.
Reaching back beyond even Obj-C, to C, this has been possible by exploiting the difference between a function prototype, commonly publicized in the header, and its implementation, commonly in a private implementation.
External and Local Parameters in C
In C, the only thing about arguments that the compiler cares about in a function prototype is the argument type; the names are purely documentary.
In the function implementation, so long as the types don’t change, you can name the formal parameters whatever you want.
So the C equivalent of the above would be:
/* prototype, in header */
void Insert(Person *const person, const NSUInteger index);
/* implementation, in .c file */
void Insert(Person *const p, const NSUInteger i)
About That Const
Take another look at the Obj-C and Swift versions of the function declaration:
- (void)insertPerson:(Person *const)p atIndex:(const NSUInteger)i;
func insert(person p: Person, index i: Int)
It’s uncommon to see const
qualifiers on arguments in Obj-C.
In this case, I was trying to remain faithful to the Swift default of const
formal arguments.
You see, a Swift function declared like so:
func insert(person p: Person, index i: Int)
accepts an implicit let
declaration of its parameters:
func insert(let person p: Person, let index i: Int)
The mutability-faithful version of the more common Obj-C declaration:
- (void)insertPerson:(Person *)p atIndex:(NSUInteger)i;
would similarly have mutable parameters in Swift:
func insert(var person p: Person, var index i: Int)
Swift parameters are const by default, and it’s great: it’s high time that was
doable without stuttering const
all over your codebase.
Summary
- Swift’s external-local parameter declarations are a continuation of Obj-C
selector chunk then parameter declarations:
Obj-C
insertPerson:(Person *const)p
becomes Swiftinsert(person p: Person)
. - Swift function parameters are
let
-declared (const) by default. Qualify a parameter withvar
if you absolutely must have it mutable:insert(var person p: Person, var index i: Int)
.