Skip to content

Instantly share code, notes, and snippets.

@danfairs
Last active November 2, 2016 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danfairs/c7839de9cc7b311bf89d4e6acb57c75e to your computer and use it in GitHub Desktop.
Save danfairs/c7839de9cc7b311bf89d4e6acb57c75e to your computer and use it in GitHub Desktop.
Where I'd use generics in scala
// Here's the simple version - first we have a conversion function, that takes a *ContentItem and converts to a *contentpb.ContentItem.
func ContentItemToPb(c *ContentItem) (*contentpb.ContentItem, error) {
if c == nil {
return nil, errors.New("ContentItemToPb: ContentItem was nil")
}
return &contentpb.ContentItem{
Id: &contentpb.ContentId{
SourceId: c.Id.SourceId,
SourceName: c.Id.SourceName,
},
Content: c.Content,
ContentType: string(c.ContentType),
}, nil
}
// Now we have a version that works with slices of the same types.
func ContentItemsToPb(items []*ContentItem) ([]*contentpb.ContentItem, error) {
pbItems := make([]*contentpb.ContentItem, len(items))
for i, item := range items {
if item == nil {
return nil, errors.New(fmt.Sprintf("ContentItem at position %s is nil", i))
}
pbItem, err := ContentItemToPb(item)
if err != nil {
return errors.New(fmt.Sprintf("Error converting item at position %s: %s", i, err.Error()))
}
pbItems[i] = pbItem
}
return pbItems, nil
}
// There are a bunch of these, all the same pattern. So what I'd really like to write is something like this:
type mapFunc func (interface{}) (interface{}, error)
func mapItems(f mapFunc, inItems []interface{}, outItems[] interface{}) error {
for i, inItem := range(inItems) {
outItem, err := mapFunc(inItem)
if err != nil {
return err
}
outItems[i] = outItem
}
}
// This should give rise to a function like:
func ContentItemsToPb2(items []*ContentItem) ([]*contentpb.ContentItem, error) {
outPbs := make([]*contentpb.ContentItem, len(items))
err := mapItems(ContentItemToPb, items, outPbs)
if err != nil {
return nil, err
}
return outPbs, nil
}
// However, this doesn't compile - the compiler complains that the ContentItemToPb function doesn't have the right signature.
// I can write a small wrapper for ContentItemToPb to convert the types 'manually' with type assertions, but I end up with a
// lot of boilerplate - actually more than just writing the original, specialised ContentItemsToPb function!
@wendigo
Copy link

wendigo commented Nov 2, 2016

Unfortunately it's the golang way - no generics so if you want to make generic slice mapping you will have to use type assertions/convertions and interface{} which is pretty ugly (remember: interface{} says nothing).

Some people uses go:generate for that. See projects like: https://github.com/dshills/yaggg or http://clipperhouse.github.io/gen/

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