These are often very at odds. And if you don't want to repeat yourself twice with two identical names... you don't have to.
And unlike Smalltalk, in Swift at least, externally unnamed but internally named is easy (just make the external name _).
How often is this an issue?
> And unlike Smalltalk, in Swift at least, externally unnamed but internally named is easy (just make the external name _).
So, visual clutter for very little gain. IMO
In our opinion, almost always.
Having shipped code in nearly two dozen different programming languages, there were very few times when I wanted my internal parameter name to be different from my external parameter name. The reasons are very simple:
- if your function is simple, you just use the params immediately, like in your `replace` example. It doesn't matter what they are called as long as their names make sense
- if your function is not simple, the parameters are usually immediately transformed into something else (mapped to different data, split to different data etc.), and their original name doesn't matter.
So this leaves a small weird case of "somehow parameter names don't make sense for the caller of the function", and I can't for the life of me come up with such an example (the example with replace in Gleam docs is not convincing, to say the least).
It is something that you start appreciating a lot more once you have used it significantly. It helps a lot with writing more self-documenting interfaces that are legible at a glance.
Another detail I did not mention is that _public names are part of the interface_. This means that two functions that differ only in the public names are distinct overloads.
To give an extremely simple example (taken from Apple's docs):
class Counter {
var count = 0
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
...
}This starts becoming even more valuable when you have more complex objects, and allows you to move (e.g. on some kind of repository class) mangling of overload names into more readable named argument overloads.
pub fn replace(
in string: String,
each pattern: String,
with replacement: String,
) {
// The variables `string`, `pattern`, and `replacement` are in scope here
}
replace(in: "A,B,C", each: ",", with: " ")
vs pub fn replace(
in: String,
each: String,
with: String,
) {
}
replace(in: "A,B,C", each: ",", with: " ")1. Labels are accidental. If all arguments automatically create labels then the programmer has not considered and deliberately designed the API. Gleam is designed to make sure that APIs are always carefully thought about and designed as appropriate.
2. Renaming a variable becomes a breaking change. We don't believe that renaming a variable should ever result in a semver major version bump.
1. Not every code is an API. And APIs exist in multiple languages that don't have labels
2. If you wanted named parameters, you could go the C# way: https://learn.microsoft.com/en-us/dotnet/csharp/programming-...
3. Since Gleam doesn't enforce labels or check labels in any way, it doesn't "make sure APIs are carefully thought out". Labels will be just as random and accidental as parameter names following the whims of the programmer who decides to use them
> Renaming a variable becomes a breaking change.
So does renaming a label.
> So does renaming a label.
In languages without this feature, any renaming breaks the API, unlike the ones with distinct internal and external names. This is not the same.
`replace(string, pattern)` is just as (if not more) readable as `replace(in, each)`.
I was specifically replying to the claim about readability.