Skip to content

Instantly share code, notes, and snippets.

@Splizard
Last active June 10, 2020 16:53
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Splizard/df4c34ffe100c624c55ddaf45ac7eeb6 to your computer and use it in GitHub Desktop.
Save Splizard/df4c34ffe100c624c55ddaf45ac7eeb6 to your computer and use it in GitHub Desktop.
Go 2 generics without syntax changes, 1 new type, 1 new builtin.
//A generics proposal for Go, introducing one new type (generic) and one new builtin function (typeof), no syntax changes.
//Function add takes arguments of any type.
//The return value is automatically inferred based on the arguments, can be inlined by the compiler.
//Both arguments must be the same type and addable or else a compiler error will be raised.
//It's the developer's responsibility to document which types can be passed to this function.
func add(a, b generic) generic {
return a+b
}
add(2, 4) //returns int(6)
add("Hello ", "World") //returns string("Hello World")[
add(2, "World") //compiler error: cannot use 2, "World" (type int, string) in arguments to add
add(struct{}{}, [2]int{}) //compiler error: cannot use struct{}{}, [2]int{} (type struct{}, [2]int) in arguments to add
//New types can be created based on the generic type.
type GenericSlice generic
//Function that creates a new slice of the provided argument with length, can be inlined by the compiler.
//The return value is converted to a GenericSlice.
func MakeSliceOf(a generic, length int) GenericSlice {
//The builtin 'typeof' function is replaced by the type of it's argument.
return GenericSlice(make([]typeof(a), length))
}
//The get method operates on explicit GenericSlice types.
//The return value is automatically inferred based on the GenericSlice, can be inlined by the compiler.
func (g GenericSlice) Get(index int) generic {
return g[index]
}
//The set method operates on explicit GenericSlice types.
//The value argument must be the subtype of the slice or a compiler error is raised.
func (g GenericSlice) Set(index int, value generic) {
g[index] = value
}
var slice = MakeSliceOf(int(0), 10)
slice.Set(0, 22)
fmt.Println(slice.Get(0)) //22
slice.Set(0, "Hello World") //compiler error: cannot use "Hello World" (type string) in arguments to slice.Set
@petar-dambovaliev
Copy link

petar-dambovaliev commented Jan 3, 2019

I like this one more than the official draft.
I don't know if it provides the same problem space coverage but it's much simpler, fewer changes, easier to implement (maybe) and easier to reason about.

One thing i would change is
return GenericSlice(make([]typeof(a), length))
to
return Generic(make(typeof(a), length))
and
var slice = MakeSliceOf(int(0), 10)
to
var slice = MakeSliceOf([]int, 10)

@extemporalgenome
Copy link

[]typeof(a) does technically involve a syntax change, since currently a builtin call cannot be used in the element portion of a type specifier.

@tooolbox
Copy link

This is pretty good. Much more understandable than the current draft IMO.

Suggest you improve the formatting by adding .go extension to your gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment