About Internal and External Parameter Names - Images: Japanese
Hey there, everyone!
Believe it or not, we've hit article 20 of the Swift Beginner's Course! If you've been following along from the start, huge props to you — that's no small feat, and it's genuinely great to have you here.
And if this is your first time visiting the site, welcome! Take your time and enjoy.
Alright, let's move on to 'internal argument names' and 'external argument names'. Internal argument names are also referred to as 'local argument names'.
Last time, we covered arguments and parameters.
So let's put what we learned to use and write something. The following is a function that outputs the area of a rectangle or square. Since the area of a rectangle is just width times height, it ends up looking like this. The function is named areaOfSquare.
func areaOfSquare(n: Int, _n: Int) { // Outputs the area of a rectangle or square.
print(n * _n)
}
areaOfSquare(n: 10, _n: 20) // Outputs the number 200.
The function above uses parameters n and _n to do its job.
That said, looking at this function, you might get the impression that the parameter names n and _n don't really tell you what values you're supposed to pass in.
This is a common issue in programming languages in general — when a function gets really complex, you can end up wondering "wait, what am I supposed to pass into this function again?" Anyone who's worked with other programming languages has probably run into this.
To help with exactly that problem, Swift provides a feature that lets you use different names for the internal argument name and the external argument name. Let's take a look at how that works.
First, if you want the internal and external argument names to be the same, that's straightforward — just write the parameter name as you normally would, just like we've been doing so far.
func areaOfSquare(width: Int, height: Int) { // Outputs the area of a rectangle or square.
print(width * height)
}
areaOfSquare(width: 10, height: 20) // Outputs the number 200.
Next, if you want the internal and external argument names to be different, here's how you do it.
func areaOfSquare(width n: Int, height _n: Int) { // Outputs the area of a rectangle or square.
print(n * _n)
}
areaOfSquare(width: 10, height: 20) // Outputs the number 200.
Take a close look at what's inside the parentheses of the function areaOfSquare above. You'll see width n: Int, height _n: Int.
By writing it as external_name internal_name: DataType, you can separate the internal and external argument names. When calling the function, you use the syntax functionName(externalName: value).
When would you actually want to separate the internal and external argument names? Say, for example, you named the parameters widthOfSquare and heightOfSquare instead of just width and height. The names are much clearer — but they're also a lot more to type every time. That's a case where splitting the internal and external names really comes in handy.
func areaOfSquare(widthOfSquare n: Int, heightOfSquare _n: Int) { // When the parameter name is long like this, using an internal argument name can be a good move.
print(n * _n)
}
areaOfSquare(widthOfSquare: 10, heightOfSquare: 20)
There's also the minor benefit of saving on file size, but given how much storage modern computers have compared to the old days, saving a few characters doesn't really make a meaningful difference.
These days, the focus has completely shifted away from squeezing out every byte or cycle — it's all about writing code that's easy for other developers to maintain.
Back in the day, people would pour real passion into shaving off a single byte...
Modern programming puts a lot of value on writing code that other developers can read easily...
Honestly, that side of things is a bit less exciting...
There was a time when the highest praise went to the kind of "black magic" programming that was completely unreadable to ordinary mortals, yet ran at blazing speed with a tiny footprint — exploiting bugs and all...
Kind of nostalgic, looking back on that era...
Now, if you want to make it so you can call a function without specifying argument names at all, you can use _. Take a look at the sample below.
func areaOfSquare(_ n: Int, _ _n: Int) {
print(n * _n)
}
areaOfSquare(10, 20)
Notice the _ n: Int, _ _n: Int part. By writing _ internal_name: DataType, you can omit the argument label entirely when calling the function.
Use this when typing out the argument name feels like too much work there's no need to specify an argument name.
In older versions of Swift, there was a syntax where you'd add # to a parameter name to make the external and internal argument names the same.
func test(#s: String, _s: String) { // Adding '#' before the parameter name made the external and internal argument names the same.
print(s)
print(_s)
}
That syntax no longer exists, so keep that in mind. In the current syntax, simply omitting the external argument name achieves the same result.
func test(s: String, _s: String) { // Just leave out the external argument name and you're good.
print(s)
print(_s)
}
test(s: "Hatsune Miku", _s: "Lily")
Regarding external argument names — in older versions of Swift, there was a rule that said "for the first argument only, the external argument name can be omitted." It looked like this.
func test(s: String, _s: String) {
print(s)
print(_s)
}
test("Hatsune Miku", _s: "Lily") // For the first argument only, writing 'externalName:' was optional.
The reasoning behind this was that "the purpose of the first argument should already be clear from the function name itself."
However, in the current version of Swift, this has been changed — you can no longer omit the external argument name unless you use _. Make sure you don't mix these up.
When rewriting older Swift files to be compatible with newer versions, you might find yourself in a situation where "the first argument's external name is already omitted everywhere... and there are way too many places to fix..."
In that case, just add _ to the first parameter in the function definition. That way, the old calling syntax will compile just fine with modern Swift.
func test(_ s: String, _s: String) { // When you're in a pinch with too many call sites to update, add '_' before the first parameter like this.
print(s)
print(_s)
}
test("Hatsune Miku", _s: "Lily") // This will run fine.
And that covers internal and external argument names! In the next article, we'll look at return and return values.
That's all for now — see you in the next one!
This article was written by Sakurama.
Author's beloved small mammal |
桜舞 春人 Sakurama HarutoA Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him. |
If you find any errors or copyright issues, please contact us.