go-opt/optional.go

172 lines
3.8 KiB
Go
Raw Normal View History

2022-08-08 17:01:41 +00:00
package opt
import (
"fmt"
)
// Optional represents an optional value.
//
// In other programming languages this is know as: an option type, or a maybe type.
//
// For example:
//
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
//
// // ...
//
// value, found := op.Get()
// if found {
// fmt.Println("value:", value)
// } else{
// fmt.Println("nothing")
// }
//
// Also, for example:
//
// var op opt.Optional[uint8] = opt.Something[uint8](101)
//
// // ...
//
// value, found := op.Get()
// if found {
// fmt.Println("value:", value)
// } else{
// fmt.Println("nothing")
// }
type Optional[T any] struct {
value T
something bool
}
// Nothing returns an optional-type with nothing in it.
//
// For example, here is an optional-type that can hold a string with nothing in it:
//
// var op opt.Optional[string] = opt.Nothing[string]()
//
// Note that the default value for any optional-type is nothing.
// So the following code it equivalent to it:
//
// var op opt.Optional[string]
//
// Also, for example, here is an optional-type that can hold a uint8 with nothing in it:
//
// var op opt.Optional[uint8] = opt.Nothing[uint8]()
//
// Again, note that the default value for any optional-type is nothing.
// So the following code it equivalent to it:
//
// var op opt.Optional[uint8]
func Nothing[T any]() Optional[T] {
var nothing Optional[T]
return nothing
}
// Something returns a optional-type with something in it.
//
// For example, here is an optional-type with the string "once twice thrice fource" in it:
//
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
//
// And, for example, here is an optional-type with the uint8 101 in it:
//
//
// var op opt.Optional[uint8] = opt.Something(uint8(101))
func Something[T any](value T) Optional[T] {
return Optional[T]{
something:true,
value:value,
}
}
// Get return the value inside of the optional-type if it is holding something.
//
// Example usage:
//
// var op opt.Optional[string]
//
// // ...
//
// value, found := op.Get()
//
// if found {
// fmt.Println("VALUE:", value)
// } else {
// fmt.Println("nothing")
// }
func (receiver Optional[T]) Get() (T, bool) {
return receiver.value, receiver.something
}
// GoString makes it that when the fmt.Fprintf(), fmt.Printf(), and fmt.Sprintf() family of functions
// renders this type with the %#v verb, that it will be easier to understand.
//
// For example:
//
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
//
// // ...
//
// fmt.Printf("op = %#v", op)
//
// // Output:
// // op = opt.Something[string]("once twice thrice fource")
//
// Also, for example:
//
// var op opt.Optional[uint8] = opt.Nothing[uint8]()
//
// // ...
//
// fmt.Printf("op = %#v", op)
//
// // Output:
// // op = opt.Nothing[uint8]()
func (receiver Optional[T]) GoString() string {
if !receiver.something {
return fmt.Sprintf("opt.Nothing[%T]()", receiver.value)
}
return fmt.Sprintf("opt.Something[%T](%#v)", receiver.value, receiver.value)
}
// WhenNothing will call fn when receiver is holding nothing.
//
// It will not call fn when receier is hold something.
//
// For example:
//
// var op opt.Optional = opt.Nothing[string]
//
// // ...
//
// op.WhenNothing(func(){
// //@TODO
// })
func (receiver Optional[T]) WhenNothing(fn func()) {
if !receiver.something {
fn()
}
}
// WhenSomething will fn when receiver is holding something.
// The value that receiver is holding will be passed as a parameter to the function fn.
//
// It will not call fn when receiver is hold nothing.
//
// For example:
//
// var op opt.Optional = opt.Something("once twice thrice fource")
//
// // ...
//
// op.WhenSomething(func(value string){
// //@TODO
// })
func (receiver Optional[T]) WhenSomething(fn func(T)) {
if receiver.something {
fn(receiver.value)
}
}