Enforcing type in "generic" code with empty interfaces - go

Sorry for the ambiguous title.
I'm reading this book http://algs4.cs.princeton.edu/home/ and I thought it would be good to implement the examples in Go as a learning exercise, however the book uses Java as its language to describe code in.
One of the first chapters discusses setting up some core datatypes/container style classes to re-use later on but I'm having trouble trying to hammer these into a Go setting, mainly because these datatypes seem to be enjoying the use of Java generics.
For example, I've written the following code
package bag
type T interface{}
type Bag []T
func (a *Bag) Add(t T) {
*a = append(*a, t)
}
func (a *Bag) IsEmpty() bool {
return len(*a) == 0
}
func (a *Bag) Size() int {
return len(*a)
}
This works in principle in the sense that I can add items to a Bag and check its size and everything. However this also means that the following code is legal
a := make(bag.Bag,0,0)
a.Add(1)
a.Add("Hello world!")
a.Add(5.6)
a.Add(time.Now())
I was just wondering if there was any way of enforcing the type so it conforms to a contract similar to
Bag<T> bagOfMyType = new Bag<T>()
e.g.
Bag<Integer> bagOfInts = new Bag<Integer>()
I know Go doesn't have generics and they're not really The Go Way, but I was just wondering if it is a possible to "enforce" anything at compile time (probably not)
Sorry for the long post
EDIT: OK so I've been looking into this a little further, I've pretty much given up with the generics side of things (I understand this is not on the roadmap for Go) so I'm thinking of doing something similar to Haskell typeclasses with interfaces, e.g.
type T interface{}
type Bag interface {
Add(t T)
IsEmpty() bool
Size() int
}
type IntSlice []int
func (i *IntSlice) Add(t T) {
*i = append(*i, t.(int)) // will throw runtime exception if user attempts to add anything other than int
}
func (i *IntSlice) IsEmpty() bool {
return len(*i) == 0
}
func (i *IntSlice) Size() int {
return len(*i)
}
The problem with this is the type enforcement is only enforced at runtime.
Anyone got any ideas how to improve on this?

I'm new to Go myself, so I'm curious if someone will have a better answer, but here's how I see it:
You want compile-time enforcement that when Add() is called on an IntSlice, its parameter is an int. Well, here's how you do that:
func (i *IntSlice) Add(t int) {
*i = append(*i, t)
}
Since there aren't generics, the Add() method is going to be different for every type of Bag, so the Bag interface, assuming you need it, becomes just:
type Bag interface {
IsEmpty() bool
Size() int
}
That makes sense to me, because you can't pass a Bag around and throw just anything in it. Knowing that something is a Bag isn't enough to know how to call Add() on it; you must know what type of Bag you're dealing with.
You could make the interface specific to the type, like IntBag, but since only one type is actually going to satisfy that interface, you might as well get rid of the interface and change the name of IntSlice to IntBag.
Basically that means giving up entirely on anything generic-like, and just creating a type with some methods that do what you want:
type IntBag []int
func (b *IntBag) Add(i int) {
*b = append(*b, i)
}
func (b IntBag) IsEmpty() bool {
return len(b) == 0
}
func (b IntBag) Size() int {
return len(b)
}
Update: Sometimes generics really would come in handy. It seems to me we're left choosing on a case-by-case basis what exactly is best for a given problem. With empty interfaces and reflection, you can get some generic-like behavior, but it tends to be ugly and you give up some compile-time type checking. Or you give up on generics and have some code-duplication. Or you just do it a totally different way.
I asked a question a few weeks ago about how I should use Go to handle problems that look to me like they need class hierarchies. The answer was basically that there is no general solution; it's all case-by-case. I think the same applies for generics: there are no generics in Go, and there's no general solution for translating generics-based solutions to Go.
There are many cases where you might use generics in another language but interfaces are perfectly adequate (or truly shine) in Go. Your example here is one where interfaces aren't really a proper replacement. See also: Go Vs. Generics.

I'm pretty well-versed with Go. Generics are a hotly-debated topic, and there is currently nothing analogous to Java generics or C++ templates. The convention at the moment is to implement a "generic" type with an empty interface and then wrap it with a specific type implementation that makes sure only elements of that type are used. Here's an example with container/list from the Go standard library.
http://play.golang.org/p/9w9H1EPHKR
package main
import (
"container/list"
"fmt"
)
type IntList struct {
innerList *list.List
}
func NewIntList() *IntList {
return &IntList{list.New()}
}
func (l *IntList) Add(i int) {
// this is the only way to add an element to the list,
// and the Add() method only takes ints, so only ints
// can be added
l.innerList.PushBack(i)
}
func (l *IntList) Last() int {
lastElem := l.innerList.Back()
// We can safely type-assert to an int, because Add()
// guarantees that we can't put a non-int into our list
return lastElem.Value.(int)
}
func main() {
l := NewIntList()
l.Add(5)
l.Add(4)
l.Add(3)
l.Add(2)
l.Add(1)
fmt.Println("Expecting 1; got:", l.Last())
}

Related

Override a specific method of interface

I want to implement a slightly customized version of an Interface. Let's take sort.Interface as an example. We already have sort.IntSlice that implements the whole interface. But I want to implement an AbsoluteSort algorithm. For that, I only want to change the Less method. Something like this:
type AbsSortedArray struct {
sort.IntSlice
}
func (a AbsSortArray) Less(i, j int) bool {
return abs(a[i]) < abs(a[j]) // this causes an error as I don't have access to underlying array here
}
func abs(i int) int {
if i < 0 {
return i * -1
}
return i
}
So basically what I want to achieve is:
Inherit other methods like Len and Swap from the parent
Override Less method, BUT not with intent of stubbing/mocking, rather I want the access to the underlying object so that I can still implement my custom logic.
I don't have access to underlying array here
Actually, you do:
func (a AbsSortArray) Less(i, j int) bool {
return abs(a.IntSlice[i]) < abs(a.IntSlice[j])
}
But this AbsSortedArray is a cumbersome data type to use (as now you must deal with a struct with a slice member, rather than using a slice directly). It would probably be much more readable and maintanable in this specific example to just provide your own from-scratch implementation.

golang function type inheritance?

Consider this example in Go language:
type I interface {
get() string
}
type S struct {}
func (s *S) get() string {
return "here!"
}
var sSupplier = func() *S {
return &S{}
}
func foo(supplier func () I) {
i := supplier()
println(i)
}
func main() {
foo(sSupplier) // compile error, type mismatch
}
Type S inherit interface I. But apparently type func () *S does not inherit func () I, so I cannot call foo with sSupplier in place of the supplier function. Is there a way to fix it without forcing sSupplier to return type I?
In java you can use generics to do something like <T extends I> void foo(Supplier<T> supplier) {...} then call foo(sSupplier); with Supplier<S> sSupplier type. I'm not sure if similar approach is possible in go?
If you think for a bit about what generics do for you, they are really a way to ask the compiler to compile, on the spot, an anonymous wrapper function or lambda or whatever is needed to map from some concrete type. That is, given something like (I'll use C++ syntax here rather than Java as I'm much more familiar with C++):
template<T>
void f(T obj) {
// do stuff with the object
}
you're telling the compiler that when it sees f(int_value) it should build a function f that takes an int, and when it sees f(struct S) it should build a function f that takes a struct S, and so on. (This is a bit more natural in Java than it is in C++'s C underpinnings since Java does the whole argument-matching thing to decide which of these various f functions to call.)
In effect, instead of writing the actual function, you write a template—hence the C++ keyword—that the compiler can use to, at compile time, produce the function you really wanted. Since Go lacks generics, it lacks this sort of template-expansion trick.
That leaves you with several obvious alternatives, though. One is exemplified by go:generate (see, e.g., Explain go generate in this example). In this particularly simple case, though, you can just write the expansion yourself in line:
foo(func() I { return sSupplier() })
See a more complete example on the Go playground. I replacd your println(i) with fmt.Printf("%#v\n", i) to print the interface object's value in a slightly more useful form.

In golang, how do I re-assign an external reference from within a function?

I'm probably not expressing this correctly in the question, but perhaps this code will make it clearer:
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(bb **Blob) {
*bb = &Blob{"Internally created by assign1"}
}
func (b *Blob) assign2() {
*b = Blob{"Internally created by assign2"}
}
func main() {
x1 := &Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
x2 := Blob{"Hello World"}
x2.assign2()
fmt.Printf("x2 = %+v\n", x2)
}
Produces, as desired:
x1 = {Message:Internally created by assign1}
x2 = {Message:Internally created by assign2}
I want to pass a reference (pointer to a pointer) into a function and have the function assign a new value to the pointer such that the calling scope will see that new value.
I've figured out the above two ways of doing this, but I'd like to know if they are actually correct or if there is some hidden flaw. Also, are either of them more idiomatic than the other?
Coming from Java, assign2 just seems wrong but I'm sure I've seen something similar in the encoding/json package. What is that actually doing?
Thanks!
James answers the mechanics of assign2. I'll touch a bit on when to use it.
Let's take a simpler example, first.
type Counter uint
func (c *Counter) Increment() {
*c += 1
}
In the counter example the entire state of the receiver is changing. Similarly for the encoding/json package the entire state of the receiver is changing. That's really the only time I would use that style.
One major advantage of the style: you can define an interface for the change, just like the GobDecoder does.
When I first saw the assign2 style it was a little grating. But then I remembered that (c *Counter) Increment gets translated to Increment(c *Counter) in the machine code and it didn't bother me anymore. I personally prefer assign1-style. (Though, there is no need for the double pointers as orignally posted.)
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(b *Blob) {
*b = Blob{"Internally created by assign1"}
}
func main() {
x1 := Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
}
Both forms are valid Go, as you've discovered.
For the assign2 case, the compiler finds that assign2 does not appear in Blob's method set, but it is part of *Blob's method set. It then converts the method call to:
(&x2).assign2()
While it can be confusing if a method then goes and changes x2 like in your example, there are a number of places in the standard library where this pattern is used. Probably the most common one is implementing custom decoding for a type with the encoding/json module: you implement the DecodeJSON method with a pointer receiver, and update the value being pointed to.

How to modify fields in struct using methods from interface?

I'm writing a small project to learn some Google Go, but after few hours of coding I found that there's an issue I can't solve on my own, neither found on the internet. My project will be containing few algorithms operating on variables implementing one interface. The thing in common of all types is that I can rate them and compare by this rating so one of methods defined in Interface should be SetRating(x int) and the problem is, since Go is copying value - I can't modify any field in it. Here's example
http://play.golang.org/p/4nyxulwzNo
Trying to find out that people is using workarounds in this convention:
http://play.golang.org/p/PUuOBZ4uM-
but I think this solution is a ugly, because I need to know all implementations of my interface in invoke func (to cast types) and really want to avoid this and write some universal code that can get any types implementing my Interface, just knowing that every implementation have method setRating(x int) and getRating(x int).
Any hints?
(Sorry for poor English and problem's description, still learning.)
You need to use the pointer because otherwise you are not modifying the underlying structure: http://play.golang.org/p/l3X4gTSAnF
package main
type Setter interface {
Set(x int)
Print()
}
type S1 struct {
X int
}
func (this *S1) Set(x int) {
this.X = x
println("Setting value")
}
func (this *S1) Print(){
println(this.X)
}
func main() {
var s1 Setter
s1 = &S1{}
s1.Set(5)
s1.Print()
}

Best practice for unions in Go

Go has no unions. But unions are necessary in many places. XML makes excessive use of unions or choice types. I tried to find out, which is the preferred way to work around the missing unions. As an example I tried to write Go code for the non terminal Misc in the XML standard which can be either a comment, a processing instruction or white space.
Writing code for the three base types is quite simple. They map to character arrays and a struct.
type Comment Chars
type ProcessingInstruction struct {
Target *Chars
Data *Chars
}
type WhiteSpace Chars
But when I finished the code for the union, it got quite bloated with many redundant functions. Obviously there must be a container struct.
type Misc struct {
value interface {}
}
In order to make sure that the container holds only the three allowed types I made the value private and I had to write for each type a constructor.
func MiscComment(c *Comment) *Misc {
return &Misc{c}
}
func MiscProcessingInstruction (pi *ProcessingInstruction) *Misc {
return &Misc{pi}
}
func MiscWhiteSpace (ws *WhiteSpace) *Misc {
return &Misc{ws}
}
In order to be able to test the contents of the union it was necessary to write three predicates:
func (m Misc) IsComment () bool {
_, itis := m.value.(*Comment)
return itis
}
func (m Misc) IsProcessingInstruction () bool {
_, itis := m.value.(*ProcessingInstruction)
return itis
}
func (m Misc) IsWhiteSpace () bool {
_, itis := m.value.(*WhiteSpace)
return itis
}
And in order to get the correctly typed elements it was necessary to write three getters.
func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}
func (m Misc) ProcessingInstruction () *ProcessingInstruction {
return m.value.(*ProcessingInstruction)
}
func (m Misc) WhiteSpace () *WhiteSpace {
return m.value.(*WhiteSpace)
}
After this I was able to create an array of Misc types and use it:
func main () {
miscs := []*Misc{
MiscComment((*Comment)(NewChars("comment"))),
MiscProcessingInstruction(&ProcessingInstruction{
NewChars("target"),
NewChars("data")}),
MiscWhiteSpace((*WhiteSpace)(NewChars(" \n")))}
for _, misc := range miscs {
if (misc.IsComment()) {
fmt.Println ((*Chars)(misc.Comment()))
} else if (misc.IsProcessingInstruction()) {
fmt.Println (*misc.ProcessingInstruction())
} else if (misc.IsWhiteSpace()) {
fmt.Println ((*Chars)(misc.WhiteSpace()))
} else {
panic ("invalid misc");
}
}
}
You see there is much code looking almost the same. And it will be the same for any other union. So my question is: Is there any way to simplify the way to deal with unions in Go?
Go claims to simplify programing work by removing redundancy. But I think the above example shows the exact opposite. Did I miss anything?
Here is the complete example: http://play.golang.org/p/Zv8rYX-aFr
As it seems that you're asking because you want type safety, I would firstly argue that your initial
solution is already unsafe as you have
func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}
which will panic if you haven't checked IsComment before. Therefore this solution has no benefits over
a type switch as proposed by Volker.
Since you want to group your code you could write a function that determines what a Misc element is:
func IsMisc(v {}interface) bool {
switch v.(type) {
case Comment: return true
// ...
}
}
That, however, would bring you no compiler type checking either.
If you want to be able to identify something as Misc by the compiler then you should
consider creating an interface that marks something as Misc:
type Misc interface {
ImplementsMisc()
}
type Comment Chars
func (c Comment) ImplementsMisc() {}
type ProcessingInstruction
func (p ProcessingInstruction) ImplementsMisc() {}
This way you could write functions that are only handling misc. objects and get decide later
what you really want to handle (Comments, instructions, ...) in these functions.
If you want to mimic unions then the way you wrote it is the way to go as far as I know.
I think this amount of code might be reduced, e.g. I personally do not think that safeguarding type Misc against containing "illegal" stuff is really helpful: A simple type Misc interface{} would do, or?
With that you spare the constructors and all the Is{Comment,ProcessingInstruction,WhiteSpace} methods boil down to a type switch
switch m := misc.(type) {
Comment: fmt.Println(m)
...
default: panic()
}
Thats what package encoding/xml does with Token.
I am not sure to understand your issue. The 'easy' way to do it would be like the encoding/xml package with interface{}. If you do not want to use interfaces, then you can do something like you did.
However, as you stated, Go is a typed language and therefore should be use for typed needs.
If you have a structured XML, Go can be a good fit, but you need to write your schema. If you want a variadic schema (one given field can have multiple types), then you might be better off with an non-typed language.
Very useful tool for json that could easily rewritten for xml:
http://mholt.github.io/json-to-go/
You give a json input and it gives you the exact Go struct. You can have multiple types, but you need to know what field has what type. If you don't, you need to use the reflection and indeed you loose a lot of the interest of Go.
TL;DR You don't need a union, interface{} solves this better.
Unions in C are used to access special memory/hardware. They also subvert the type system. Go does not have the language primitives access special memory/hardware, it also shunned volatile and bit-fields for the same reason.
In C/C++ unions can also be used for really low level optimization / bit packing. The trade off: sacrifice the type system and increase complexity in favor of saving some bits. This of course comes with all the warnings about optimizations.
Imagine Go had a native union type. How would the code be better? Rewrite the code with this:
// pretend this struct was a union
type MiscUnion struct {
c *Comment
pi *ProcessingInstruction
ws *WhiteSpace
}
Even with a builtin union accessing the members of MiscUnion requires a runtime check of some kind. So using an interface is no worse off. Arguably the interface is superior as the runtime type checking is builtin (impossible to get wrong) and has really nice syntax for dealing with it.
One advantage of a union type is static type check to make sure only proper concrete types where put in a Misc. The Go way of solving this is "New..." functions, e.g. MiscComment, MiscProcessingInstruction, MiscWhiteSpace.
Here is a cleaned up example using interface{} and New* functions: http://play.golang.org/p/d5bC8mZAB_

Resources