Archive for July, 2017

Go experience report: the append function

When the Go language was first publicly released it contained a package named container/vector.  The type vector.Vector was a name for the type []interface{}.  Vector supported methods like Len, Cap, At, Set, Insert, Delete, Push, Pop, and several more.  You can see the source code at on Github.  An interesting aspect of the package is that string and int versions of Vector were automatically generated by copying the file vector.go with edits applied by gofmt -r.

The container/vector package was deleted in October, 2011, before the Go 1 release, because by that time it added nothing that was not available more simply using slices.  But it was useful once; in October, 2010, it was used by 18 packages in the standard library.  By the time it was deleted one year later, it was not used by any.  This change occurred because of a key feature added to the language: the built-in append function.

The append function was first proposed by Robert Griesemer in an internal e-mail sent in November, 2009, during a discussion of whether to add the built-in copy function (as a result of that discussion copy was added to the language in CL 156089).  At that time I replied about both copy and append saying “It seems to me that these functions are not useful if we figure out a way to implement generics. Not necessarily a strong argument against them, I suppose, but do we want to introduce new builtin functions if we may not need them?”

In 2009 we added copy but not append.  In October, 2010, David Symonds proposed append independently, saying “It’s been getting tiresome having to write the same old boilerplate to grow a slice on demand. container/vector would be suitable if it were generic, but cluttering code with type assertions is worse than the expansion.”  Robert picked this up and outlined the function we know today, adding “Should we ever have some form of genericity, this could even become a library function. For now, the implementation would be a built-in.”  I replied to the thread, essentially repeating myself from a year before: “I’m not really opposed to a builtin append function but I want to make the obvious comment that, like copy, this is a function we are only considering because we don’t have generics.”  The result of this discussion was to add append as we know it today to the Go language (CL 2627043).

The point I want to make here is that because we had no way to write a generic Vector type with an Append method, we wound up adding a special purpose language feature to implement it.  A language that supported parameterized types with methods would not have required a special built-in function that only works with slices.  An append operation makes sense for other sorts of data structures, such as various kinds of linked lists.  The built-in append function can not be used for them.

I am writing this note as a user experience report to add to the Go wiki.  To fit the format there, what we wanted to do was to add a generally useful mechanism for extending a slice.  What we had to do was extend the language.  That wasn’t great because it made the language more complex by adding a special purpose, non-generalizable, non-orthogonal, feature.

Comments