Hi there,
I played around a bit with the go2go playground today; I was wondering
how useful it would be to implement enums.
Whether using generics like this is a good idea or not is a different
discussion, it's just an interesting thing to experiment with and see
how far I could get.
I thought it might be useful to share my experience; I ran in to several
errors I couldn't really make sense of. This is probably a failure of
understanding on my part 😅 But I did spend quite some time in front of
the draft specification trying to figure this out.
All code was run on the "go2go" playground today.
Note I am not usually subscribed to the golang-nuts mailing list, and
have not read all of the discussions (using Google groups to browse
archives is a but of a pain), so apologies if this duplicates any
previous feedback.
Hope it helps.
Cheerio,
Martin
---
First, let's define my types:
type (
Banana struct{ banana struct{} }
Coconut struct{ coconut struct{} }
Fruit interface {
type Banana, Coconut
}
)
And then adds a function which only accepts a "Fruit" enum value:
func show(type enum Fruit)(fruit enum) {
switch (interface{})(fruit).(type) {
case Banana:
fmt.Println("That's just bananas!")
case Coconut:
fmt.Println("I've got a lovely bunch of coconuts!")
default:
fmt.Println("Yeah nah")
}
}
func main() {
show(Banana{})
show(Coconut{})
}
The type switch is somewhat ugly and has limitations, as mentioned in
the design document, but it works for this case.
Moving on, I wanted to add a function which accepts multiple fruits,
which gives an error:
// type Coconut of (Coconut literal) does not match inferred type
Banana for enum
func showAll(type enum Fruit)(fruits ...enum) {
for _, f := range fruits {
show(f)
}
}
In the spec it actually mentioned that:
> No variadic type parameters. There is no support for variadic type
> parameters, which would permit writing a single generic function that
> takes different numbers of both type parameters and regular
> parameters.
So looks like that's not supported, fait enough, but the error message
is a bit confusing. Second try:
func showAll(type enum Fruit)(fruits []enum) {
for _, f := range fruits {
show(f)
}
}
func main() {
// Fruit does not satisfy Fruit (interface{type Banana,
Coconut} not found in Banana, Coconut)
showAll([]Fruit{Banana{}})
}
I'm not entirely sure what to make of that error 🤔
Adding a function which returns a Fruit also proved difficult:
// cannot use (Banana literal) (value of type Banana) as enum value in
return statement
func getBanana(type enum Fruit)() enum {
return Banana{}
}
// cannot convert (Banana literal) (value of type Banana) to enum
func getBanana(type enum Fruit)() enum {
return enum(Banana{})
}
I'm not entirely sure why this doesn't work 🤔 It does work when you're
doing something like:
// getBanana(Banana{})
func getBanana(type enum Fruit)(v enum) enum {
return v
}
But this is a fairly useless function :-)
I also wasn't able to create a list of all Fruit types:
// undefined: Fruit
var FruitList = []Fruit{Banana{}, Coconut{}}
func FruitList(type enum Fruit)() enum {
// cannot use (Banana literal) (value of type Banana) as enum
value in array or slice literal
return []enum{Banana{}, Coconut{}}
}
// function type must have no type parameters
var FruitList = func(type enum Fruit)() []enum {
return []enum{}
}
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/f7c19f07-809c-4cb2-9815-6d9a1b88d5f9%40www.fastmail.com.