StabbyCutyou / generics

Package generics is the true way to program generically in golang
Apache License 2.0
193 stars 9 forks source link

Examples for generics #11

Open zythosec opened 7 years ago

zythosec commented 7 years ago

Would it be possible to get some practical examples on how to use this package (preferably in the godoc)? This will ensure consistent use of G and help newcomers like me use generics properly.

StabbyCutyou commented 7 years ago

This is an excellent idea. I'd welcome you to open a PR if you have specific examples in mind, or provide them here and I can add them into the next release.

zythosec commented 7 years ago

It would be great to have examples for generic lists, generic interfaces, generic methods, etc. Basically, as close to as possible to generic implementations listed on the C# Programming guide here: https://msdn.microsoft.com/en-us/library/512aeb7t.aspx

Keep in mind, however, I understand the large impact that may have on the maintainer of this project so if you feel it necessary, I can split this request up into multiple issues. Additionally, I further understand that Go is not C#, so not all of these may be possible, and I am relying on you, the maintainer, to show what IS possible.

StabbyCutyou commented 7 years ago

I'll give this some thought. I've got a few irons in the fire around testability and repeatable builds, so I don't want to slap this together hastily and have it underserve the community.

Thank you for your thoughtful and well articulated feature request

benjamin-rood commented 7 years ago

This is a complicated problem. Herein lies some semi-coherent ramblings:

I think once you start trying to create generic containers in Go, you inevitably want to use a non-empty interface to define the required behaviour between the elements held in the data structure. For most structures, you need a way of defining the ordering relation between elements, i.e. a comparison... then before you know it you are defining something almost identical to the sort interface.

If you want a list: type glist []G – that's really all you need as slices have all the necessary methods to execute list behaviour. If you want a linked-list (and you probably don't):

type G interface{}

type List interface {
    Head() G
    Tail() G
    Append(G)
    AppendHead(G)
    Pop() G
    PopHead() G
    Length() int
}

type Node struct {
    g    G
    prev *Node
    next *Node
}

type Listy struct {
    headptr *Node
    tailptr *Node
    length  int
}

    func (l *Listy) Head() G {
    return l.headptr.g
}

func (l *Listy) Tail() G {
    return l.tailptr.g
}

func (l *Listy) Length() G {
    return l.length
}

func (l *Listy) Append(g G) {
    l.tailptr = &Node{
        g:    g,
        next: nil,
        prev: l.tailptr,
    }
    l.length++
}

func (l *Listy) AppendHead(g G) {
    l.headptr = &Node{
        g:    g,
        next: l.headptr,
        prev: nil,
    }
    l.length++
}

func (l *Listy) Pop() G {
    if l == nil {
        return nil
    }
    value := l.tailptr.g
    l.tailptr = l.tailptr.prev
    l.tailptr.next = nil
    l.length--
    return value
}

func (l *Listy) PopHead() G {
    if l == nil {
        return nil
    }
    value := l.headptr.g
    l.headptr = l.headptr.next
    l.tailptr.prev = nil
    l.length--
    return value
}

There's a list interface in there just for kicks, but really, it would make more sense to have a set of interfaces which define the characteristics of generic containers and the data they hold. This is analogous to the generic methods on a collection.

But other than a list, what other 'dumb' containers are there? A Set? Check out this gset trifle, I tried to play with creating one now. You can pass in any type of object just the same way you would a Pythonic set. You can perform the standard set operations like union and intersection. (It's dumb, but fun playing with it for a bit)

In either case though, you have a significant problem: How do you know what the ACTUAL types of the stuff in the collection are, so that you can perform operations on individual data values? I'm not saying there isn't some value in these sorts of collections, but I feel like there's something missing in the equation.

Think about the "advanced" container types in the C++ standard library. They only support one type per collection and they often require an ordering relation (in the form of a lambda) to work. Well, defining an interface is so much more versatile and powerful in my opinion, especially as you can combine them. Then, if it's just going to be on one type, or on a set of types, set the type as an explicit interface.

Otherwise, the most obvious use for this is for going between a relational database with the defined schema: map[string]G – and then the string key is the field name.

StabbyCutyou commented 7 years ago

I believe the issue in question is centering more around every day best uses of G and not necessarily looking to endorse G as something for an IoC container - however I'd never tell someone they couldn't use G for this either.

Thanks for the implementation of a LL, I'll be sure to include it with credit once I have the examples section in better shape.

benjamin-rood commented 7 years ago

Gotcha.

Once I have thought and played with the gset thing a bit more I will let you know.

On 11/10/2016, at 1:03 AM, StabbyCutyou notifications@github.com wrote:

I believe the issue in question is centering more around every day best uses of G and not necessarily looking to endorse G as something for an IoC container - however I'd never tell someone they couldn't use G for this either.

Thanks for the implementation of a LL, I'll be sure to include it with credit once I have the examples section in better shape.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.