Skip to content

Instantly share code, notes, and snippets.

@strategicpause
Last active December 16, 2021 06:54
Show Gist options
  • Save strategicpause/e038a0dc7beabb752b72166b3daa06e3 to your computer and use it in GitHub Desktop.
Save strategicpause/e038a0dc7beabb752b72166b3daa06e3 to your computer and use it in GitHub Desktop.
golang1.18
package main
import (
"fmt"
)
// Based off of the Java Optional<T> type.
type Optional[T any] struct {
value *T
}
type Consumer[T any] func(T)
type Predicate[T any] func(T) bool
type Supplier[T any] func() T
type Function[T, U any] func(T) U
func Empty[T any]() Optional[T] {
return Optional[T] { value: nil }
}
func Of[T any](value T) Optional[T] {
return Optional[T] { value: &value }
}
func (o Optional[T]) Get() T {
if o.value == nil {
panic("Empty optional")
}
return *o.value
}
func (o Optional[T]) OrElse(value T) T {
if o.value == nil {
return value
}
return *o.value
}
func (o Optional[T]) OrElseGet(supplier Supplier[T]) T {
if o.value == nil {
return supplier()
}
return *o.value
}
func (o Optional[T]) IfPresent(consumer Consumer[T]) {
if o.value != nil {
consumer(*o.value)
}
}
func (o Optional[T]) Filter(predicate Predicate[T]) Optional[T] {
if o.value == nil {
return o
}
if predicate(*o.value) {
return o
}
return Empty[T]()
}
// Apparently you can't add additional types in methods, so I had to implement this as a function.
func Map[T, U any](o Optional[T], f Function[T,U]) Optional[U] {
if &o.value == nil {
return Empty[U]()
}
return Of(f(*o.value))
}
func main() {
// Prints 236
Map(Of(123), func(x int) int { return x * 2 }).IfPresent(func(x int) { fmt.Println(x) })
// Prints 0
value := Of(123).Filter(func(x int) bool { return x % 2 == 0 }).OrElse(0)
fmt.Println(value)
// Prints 1234
value = Empty[int]().OrElseGet(func() int { return 1234 })
fmt.Println(value)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment