Skip to content

Commit

Permalink
Merge pull request #7 from orsinium-labs/builder
Browse files Browse the repository at this point in the history
Add enum.Builder
  • Loading branch information
orsinium authored Sep 3, 2023
2 parents 527edcb + 97661b1 commit b7aa223
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 0 deletions.
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
linters:
disable:
- dupword
- depguard
presets:
- bugs
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ var (
fmt.Println(Red.Value.UI)
```

If the enum has lots of members and new ones may be added over time, it's easy to forget to register all members in the enum. To prevent this, use enum.Builder to define an enum:

```go
type Color enum.Member[string]

var (
b = enum.NewBuilder[string, Color]()
Red = b.Add(Color{"red"})
Green = b.Add(Color{"green"})
Blue = b.Add(Color{"blue"})
Colors = b.Enum()
)
```

## 🤔 QnA

1. **What happens when enums are added in Go itself?** I'll keep it alive until someone uses it but I expect the project popularity to quickly die out when there is native language support for enums. When you can mess with the compiler itself, you can do more. For example, this package can't provide an exhaustiveness check for switch statements using enums (maybe only by implementing a linter) but proper language-level enums would most likely have it.
Expand Down
32 changes: 32 additions & 0 deletions enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,35 @@ func (e Enum[M, V]) GoString() string {
joined := strings.Join(values, ", ")
return fmt.Sprintf("enum.New(%s)", joined)
}

// Builder is a constructor for an [Enum].
//
// Use [Builder.Add] to add new members to the future enum
// and then call [Builder.Enum] to create a new [Enum] with all added members.
//
// Builder is useful for when you have lots of enum members, and new ones
// are added over time, as the project grows. In such scenario, it's easy to forget
// to add in the [Enum] a newly created [Member].
// The builder is designed to prevent that.
type Builder[M iMember[V], V comparable] struct {
members []M
finished bool
}

// NewBuilder creates a new [Builder], a constructor for an [Enum].
func NewBuilder[V comparable, M iMember[V]]() Builder[M, V] {
return Builder[M, V]{make([]M, 0), false}
}

// Add registers a new [Member] in the builder.
func (b *Builder[M, V]) Add(m M) M {
b.members = append(b.members, m)
return m
}

// Enum creates a new [Enum] with all members registered using [Builder.Add].
func (b *Builder[M, V]) Enum() Enum[M, V] {
b.finished = true
e := New(b.members...)
return e
}
13 changes: 13 additions & 0 deletions enum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,16 @@ func TestEnum_Index_Panic(t *testing.T) {
}()
Colors.Index(Color{"purple"})
}

func TestBuilder(t *testing.T) {
is := is.New(t)
type Country enum.Member[string]
var (
b = enum.NewBuilder[string, Country]()
NL = b.Add(Country{"Netherlands"})
FR = b.Add(Country{"France"})
BE = b.Add(Country{"Belgium"})
Countries = b.Enum()
)
is.Equal(Countries.Members(), []Country{NL, FR, BE})
}
19 changes: 19 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,22 @@ func ExampleEnum_TypeName() {
fmt.Println(tname)
// Output: string
}

func ExampleNewBuilder() {
type Color enum.Member[string]
var (
b = enum.NewBuilder[string, Color]()
Red = b.Add(Color{"red"})
Green = b.Add(Color{"green"})
Blue = b.Add(Color{"blue"})
Colors = b.Enum()
)

fmt.Println(
Colors.Contains(Red),
Colors.Contains(Green),
Colors.Contains(Blue),
)
// Output:
// true true true
}

0 comments on commit b7aa223

Please sign in to comment.