Generics to the rescue!



Generics to the rescue!

0 2


generating_generics


On Github ehrenmurdick / generating_generics

Ehren Murdick

@rubyprogrammer

github.com/ehrenmurdick

Generating Generics

Pyramid of errors

doc1 := entities.NewDocument("document 1")
_, err := printDocument(doc1)
if err != nil {
  printError(err)
} else {
  _, err = saveDocument(doc1)
  if err != nil {
    printError(err)
  }
}
  • Duplicated error handling
  • Hard to understand
  • Lots of boilerplate
  • Catch problems at build time

Container!

type OptionalDocument interface {
  Try(func(Document) (Document, error)) OptionalDocument
  HandleErr(func(error) error) OptionalDocument
}
func printDocument(d Document) (Document, error)

Using OptionalDocument

doc2 := entities.NewDocument("document 2")
opt2 := optionals.WrapDocument(doc2)
opt2.
  Try(printDocument).
  Try(saveDocument).
  HandleErr(printError)
  • Easy to understand
  • Handle error once
  • Catch problems at build time
  • Lots of boilerplate

Contain Anything

type OptionalAny interface {
  Try(f func(interface{}) (interface{}, error)) OptionalAny
  HandleErr(f func(error) error) OptionalAny
}
func printAny(i interface{}) (interface{}, error)

Using OptionalAny

doc3 := entities.NewDocument("document 3")
opt3 := optionals.WrapAny(doc3, nil)
opt3.
  Try(printAny).
  Try(saveAny).
  HandleErr(printError)
  • Handle error once
  • Easy to understand
  • Not a lot of code
  • Problems come up at run time

Generics to the rescue!

An example in Swift

struct Stack<Item> {
  var items = [Item]()
  func pop() -> Item
}

…is basically just generating…

struct StackInteger {
  var items = [Integer]()
  func pop() -> Integer
}
struct StackString {
  var items = [String]()
  func pop() -> String
}

We can generate too! (at build time)

//go:generate ./optional Document
type Optional<%= Item %> interface {
  Try(func(<%= Item %>) (<%= Item %>, error)) Optional<%= Item %>
  HandleErr(func(error) error) Optional<%= Item %>
}

Using Optional<%= Item %>

doc3 := entities.NewDocument("document 2")
opt3 := optionals.WrapDocument(doc2)
opt3.
  Try(printDocument).
  Try(saveDocument).
  HandleErr(printError)
  • Handle error once
  • Not a lot of code
  • Problems caught at build time
  • Hard to understand

Dont use it

Links

github.com/ehrenmurdick/container_talk

github.com/ehrenmurdick/generating_generics

Ehren Murdick @rubyprogrammer github.com/ehrenmurdick