Ehren Murdick
@rubyprogrammer
github.com/ehrenmurdick
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)
  }
}
        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)
        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)
        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)