In the previous two posts, I started this rant about why some of Go’s convenience features are actually anti-helpful. In this post, I’ll mention a new one: Function parameters that share types.
A function declaration in Go looks pretty normal:
func f(x int, y bool) int
and so forth. The types come after the names, but that’s how Go does it. I don’t love how it looks, but they make a reasonable case for the decision.
The strange version of this is that multiple parameters that share the same type can share a single instance of the type’s name. For example:
func f(x, y int, z bool)
declares f to take two int parameters: x and y. This syntax flows from the similar variable declaration syntax:
var x, y, z int
This isn’t ambiguous in either case, so it seems like it should be elegant to allow the same syntax in both places. Plus, it saves typing out the type name repeatedly. However, for me at least, I find the function syntax consistently confusing; I always have to go back and re-read the declaration a couple of times to sort out which types go with which variables.
Here is the difference between the two scenarios: In a variable declaration
that includes a type, the entire line is dedicated to listing variables of a
single type. var x, y, z int
reads as “Variables x, y, and z have type
int.” By contrast, I always want to read f(x, y int, z bool)
as “Function
f takes parameters x, y of type int, and z of type bool.” I know
that x needs a type, so I have to stop and re-read it to remind myself that
x and y actually get the same type.
This is easy for the compiler to parse, but hard for humans to parse. That’s exactly the wrong thing to do; the computer should do more work to make the programmer’s life easier.
In this case, I think the problem comes from using the same punctuation for both dividers (the one where the next parameter has the same type and the one where the next parameter has a different type). The Go blog I linked above criticizes C-style declarations for putting names in the middle of types, but this doesn’t seem too different. When I see x, I have to read forward to find the int, then come back to the x and continue forward to the next variable. This seems like it could be fixed by changing punctuation, e.g.
func f(x, y int; z bool)
Then instead of the comma telling you that the declaration is done, it would tell you that another variable of the same type is coming. Unfortunately, this would lead to the simple case being very different from what people are used to:
func f(x int; y int; z bool)
I’m not sure that would ultimately be an improvement.