Author(s): Leszek Dubiel
Last updated: 2016-04-20
Go's syntax is clean and compact, but still verbose. Keywords are short and idomatic -- func to define function, not a full word function, var for variable, const for constant.
Keyword interface doesn't fit that rules and because it's long, reading programs that use lots of interfaces is hard.
This proposal doesn't aim at reducing number of keystrokes, but to improve readability.
Long interface keyword is very dominant:
func Map(f func(interface{}) interface{}, xs []interface{}) []interface{} {
var ys = make([]interface{}, len(xs))
}
type shape interface {
area() float64
}
This is easier to read:
func Map(f func(iface{}) iface{}, xs []iface{}) []iface{} {
var ys = make([]iface{}, len(xs))
}
type shape iface {
area() float64
}
More examples (http://bouk.co/blog/idiomatic-generics-in-go/):
func Map(in interface{}, fn func(interface{}) interface{}) interface{} {
val := reflect.ValueOf(in)
out := make([]interface{}, val.Len())
for i := 0; i < val.Len(); i++ {
out[i] = fn(val.Index(i).Interface())
}
return out
}
func Reduce(in interface{}, memo interface{}, fn func(interface{}, interface{}) interface{}) interface{} {
val := reflect.ValueOf(in)
for i := 0; i < val.Len(); i++ {
memo = fn(val.Index(i).Interface(), memo)
}
return memo
}
func Filter(in interface{}, fn func(interface{}) bool) interface{} {
val := reflect.ValueOf(in)
out := make([]interface{}, 0, val.Len())
for i := 0; i < val.Len(); i++ {
current := val.Index(i).Interface()
if fn(current) {
out = append(out, current)
}
}
return out
}
versus:
func Map(in iface{}, fn func(iface{}) iface{}) iface{} {
val := reflect.ValueOf(in)
out := make([]iface{}, val.Len())
for i := 0; i < val.Len(); i++ {
out[i] = fn(val.Index(i).Interface())
}
return out
}
func Reduce(in iface{}, memo iface{}, fn func(iface{}, iface{}) iface{}) iface{} {
val := reflect.ValueOf(in)
for i := 0; i < val.Len(); i++ {
memo = fn(val.Index(i).Interface(), memo)
}
return memo
}
func Filter(in iface{}, fn func(iface{}) bool) iface{} {
val := reflect.ValueOf(in)
out := make([]iface{}, 0, val.Len())
for i := 0; i < val.Len(); i++ {
current := val.Index(i).Interface()
if fn(current) {
out = append(out, current)
}
}
return out
}
Add iface keyword that is an alias of interface. After a few years have passed add compiler warning about obsolete long interface. It would be backwards compatibile.
iface is commonly used as an identifier today. How do you propose adding it as a keyword while remaining backwards compatible?
You're right. Please tag this for "Go2" for far future.
I don't want this alias even for Go 2. How is using iface more readable
than interface? Humans don't read letter by letter....
function in Javascript). Go's keywords func, chan, var, go are short and elegant. func doesn't disturb clarity, while interface does. While iface is obliviously shorter, interface is more readable and understandable.
Defining a new interface does not happen very often so the shortness of iface does not make up for the loss of readability here.
The keyword iface could shorten signatures of functions with empty interfaces like in your examples but using empty interfaces is not a practice that needs to be encouraged.
This makes writing easier, but I disagree that it makes reading easier in the common case. Your "generic map" function is not representative of the majority of Go code, and the interface keyword appears far less than one instance per line on average, even when you measure only function signatures. (You also could have written type T interface{} and used T and []T throughout your signature)
JavaScript code has proportionally more functions than Go has either functions or interfaces. Arguments for shortening the function syntax in that language may not apply with equal magnitude in this language.
The counter-point I find more compelling is that func-tion, chan-nel, var-iable are all fairly unambiguous prefixes in addition to being abbreviations. iface is not a prefix, thus has a different tone/feel when reading or discussing it. If fn had been chosen as the function keyword, I might not have this reservation.
I'm not personally in favor of this. Perhaps interface is on the long side, but iface does not seem like a good substitute.
I am not a fan of this. I don't think it buys anything. If there is any principle that one might apply to the choice if keywords, it might be that frequently used keywords for simple concepts should be compact, while others (for more complex and less frequently used ones) can be longer.
I'm very much a fan of succinct names in local context, and longer names in larger context, but there are exceptions (such as widely used constants in global contexts, etc.). But I am not fond of mangling keywords for shortness.
interface is common but not that common. Note that keywords are usually not shortcut in Go with a few exceptions: var, const, and struct, really for historic reasons (and they are reasonably frequent). The very first spec versions used functionnot func, and the only other one that's abbreviated is chan.
I like @extemporalgenome's counter-point, all the abbreviated keywords we have are prefixes that naturally extend to full length when spoken.
I don't like this: "iface" sounds ugly and is not even a proper abbreviation or prefix, as @griesemer points out.
There are many things that could be improved in Go, maybe for a second version, but the spelling of interface is not a problem that needs to be fixed.
Most helpful comment
I don't want this alias even for Go 2. How is using iface more readable
than interface? Humans don't read letter by letter....