natsu

command module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 27, 2022 License: MIT Imports: 7 Imported by: 0

README

夏 – natsu – summer.

sum type generator for go 1.18+

Usage

For a module with natsu in the go.mod file, a sum type can be generated by adding the following to a .go source file:

//go:generate go run github.com/butzopower/natsu <pkg> <union> <sumTypeToGenerate>

For example:

package models

type Cat struct { NumLives int }
type Dog struct { Tricks []string }

//go:generate go run github.com/butzopower/natsu my/package/models pet Pet
type pet interface {
    Cat | Dog
}

Running go generate in this directory will generate a file pet.go that can be used like so:

package main

import "my/packages/models"

func main() {
    var petCat models.Pet
    var petDog models.Pet

    petCat = models.PetOf(models.Cat{NumLives: 9})
    petDog = models.PetOf(models.Dog{Tricks: []string{"sit", "stay"}})

    exec := models.PetExecutor().
        WithCat(func(cat models.Cat) { println("the cat has " + cat.NumLives + " lives")}).
        WithDog(func(dog models.Dog) { 
            println("our dog knows the following tricks:")
            for _, trick := range dog.Tricks {
                println(" - " + trick)
            }
        })
    
    exec.Exec(petCat) // output: 
                      // the cat has 9 lives
    
    exec.Exec(petDog) // output: 
                      // our dog knows the following tricks:
                      //  - sit
                      //  - stay

    mapFn := models.PetMapper[string]().
        WithCat(func(cat models.Cat) string { 
            return "<div class=\"cat\">Lives: " + cat.NumLives + "</div>"
        }).
        WithDog(func(dog models.Dog) string {
            var sb strings.Builder
            sb.WriteString("<ul>")

            for _, trick := range dog.Tricks {
                sb.WriteString("<li>" + trick + "</li>")
            }

            sb.WriteString("</ul>")
            return sb.String()
        })

    catElement := mapFn.Map(petCat)
    dogElement := mapFn.Map(petCat)

    print(catElement) // <div class="cat">Lives: 9</div>
    print(dogElement) // <ul><li>sit</li><li>stay</li></ul>
}

Why

What benefit does a sum type provide over a type switch?

Consider the below example of function constrained by a type union that uses a type switch:

type Cat struct {
    Name string 
    SharpClaws bool
}

type Dog struct {
    Name string
    Trained bool
}

type Pet interface {
    Cat | Dog
}

func Cuddle[T Pet](pet T) {
    var switchablePet interface{} // ❌ required as can not switch on type constraint
    switchablePet = pet
    switch p := switchablePet.(type) {
    case Cat:
        if p.SharpClaws {
            print("ow, it scratched me")
        }
    case Dog:
        if !p.Trained {
            print("ah, it slobbered me")
        }
    case string: // ❌ allowed as can not check exhaustively
        print("uh wut")
    default:     // ❌ required as can not check exhaustively
        print("there is no pet?")
    }
}

func main() {
    Cuddle(Cat{Name: "Tex", SharpClaws: true})
    Cuddle(Dog{Name: "Fifi", Trained: false})
    
    // ✅ does not compile: string does not implement Pet 
    Cuddle("strings are what cats play with")
}

Inspiring Projects

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL