Sure. Option A, the one I recommend, is that function types do not have labels. The type of fn removeAll(&mut self, equalTo value: T)
and the type of fn append(&mut self, _ value: T)
are both fn(&mut Self, T)
.
Option B is to keep the labels in the type, giving you fn(&mut Self, equalTo: T)
and fn(&mut Self, T)
. From my perspective, this has a few problems:
-
The labels don’t necessarily make sense without the base name, and when you’re using function pointers (or function traits), you’ve got more than one possible value, with no guarantee they have the same labels. Heck, while I’ve never seen functions actually named
add(to: Set<T>)
andremove(from: Set<T>)
, surely they should have the same type! -
If labels are part of the type system…are two different function types compatible? Can
removeAll(equalTo:)
be passed to a parameter of typefn(&mut Self, T)
? Probably! But what aboutfn(&mut Self, value: T)
? Is this a new implicit conversion? Can you changefn(x: f64, y: f64)
tofn(y: f64, x: f64)
? -
What happens when you put
fn(value: isize)
intodyn Any
? Can you get it out asfn(isize)
? Asfn(offset: isize)
? -
Putting the labels in the type undermines the user model of “these functions have different names”. (I guess this only matters if you have name-based overloading, which I’m willing to call it. I’ve got some thoughts on Python-style labels without overloading but I’m still working them out.)
Now, there is a downside of Option A too: sometimes function pointers really would benefit from labels. But those labels go with the name of the function pointer argument, not what gets passed to it. We had the idea in Swift that
fn for_each(
&self,
apply process: impl FnMut(key: K, value: V)
) {
// Yes, this is inefficient, don’t worry about it.
for k in self.keys() {
process(key: k, value: self[k])
}
}
would be sugar for something like
fn for_each(
&self,
apply process(key:value:): impl FnMut(K, V)
) {
for k in self.keys() {
process(key: k, value: self[k])
}
}
but never got around to implementing it. (Still could some day, though; we left space for it.) It’s not strictly necessary, and since there are always functions without labels it’s not out-of-place or anything.
So yeah, don’t go with Option B.