optional

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2024 License: GPL-3.0 Imports: 0 Imported by: 0

README

Go Generics: Optional

Go Reference Go Report Card

Implementation of an optional type.

Documentation

Overview

Package optional implements an optional value, also sometimes called "Maybe".

The package is written in a functional style, with many top-level functions that revolve around a simple value type.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Else added in v1.2.0

func Else[T any](value Value[T], onEmpty func())

Else calls onEmpty for values that are empty. Nothing is done if the value actually wraps an item. onEmpty may be nil.

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	valueWithItem := optional.NewWithItem("I am an item.")
	emptyValue := optional.NewEmpty[string]()

	optional.Else(
		valueWithItem,
		func() {
			fmt.Println("First.")
		},
	)

	optional.Else(
		emptyValue,
		func() {
			fmt.Println("Second.")
		},
	)

}
Output:

Second.

func GetItem

func GetItem[T any](value Value[T]) (T, bool)

GetItem extracts the item from value if such an item exists. If not, the zero value for T is returned. The second return value signals whether a value could be extracted.

func HasItem

func HasItem[T any](value Value[T]) bool

HasItem checks whether the value actually contains an item. Opposite of IsEmpty().

func If added in v1.2.0

func If[T any](value Value[T], onValue func(T))

If calls onValue for values wrapping an item, passing said item. Nothing is done if the value is empty. onValue may be nil.

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	valueWithItem := optional.NewWithItem("I am an item.")
	emptyValue := optional.NewEmpty[string]()

	optional.If(
		valueWithItem,
		func(s string) {
			fmt.Println("First: " + s)
		},
	)

	optional.If(
		emptyValue,
		func(s string) {
			fmt.Println("Second: " + s)
		},
	)

}
Output:

First: I am an item.

func IfElse

func IfElse[T any](value Value[T], onValue func(T), onEmpty func())

IfElse calls onValue for values wrapping an item, passing said item. If the value is empty, onEmpty is called instead. Both onValue and onEmpty may be nil.

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	valueWithItem := optional.NewWithItem("I am an item.")
	emptyValue := optional.NewEmpty[string]()

	printItem := func(s string) {
		fmt.Println(s)
	}
	printDefault := func() {
		fmt.Println("I am empty.")
	}

	optional.IfElse(
		valueWithItem,
		printItem,
		printDefault,
	)

	optional.IfElse(
		emptyValue,
		printItem,
		printDefault,
	)

}
Output:

I am an item.
I am empty.

func IsEmpty

func IsEmpty[T any](value Value[T]) bool

IsEmpty checks whether the value is empty. Opposite of HasItem().

func Len

func Len[T any](value Value[T]) int

Len returns the number of items. This is 1 for a value containing an item, else 0.

func ToSlice

func ToSlice[T any](value Value[T]) []T

ToSlice returns the slice with the items wrapped by the value. Contains at most 1 item.

Types

type Value

type Value[T any] interface {
	// Invoke calls f only if an item is stored with that value.
	Invoke(f func(item T))
}

Value represents an optional value. It may contain an item of type T.

Example (Empty)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	value := optional.NewEmpty[int]()

	item, ok := optional.GetItem(value)
	fmt.Println(item)
	fmt.Println(ok)

	fmt.Println(optional.HasItem(value))
	fmt.Println(optional.IsEmpty(value))
	fmt.Println(optional.Len(value))
	fmt.Println(len(optional.ToSlice(value)))

}
Output:

0
false
false
true
0
0
Example (WithItem)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	value := optional.NewWithItem("Hello, world!")

	item, ok := optional.GetItem(value)
	fmt.Println(item)
	fmt.Println(ok)

	fmt.Println(optional.HasItem(value))
	fmt.Println(optional.IsEmpty(value))
	fmt.Println(optional.Len(value))
	fmt.Println(len(optional.ToSlice(value)))

}
Output:

Hello, world!
true
true
false
1
1

func Dereference

func Dereference[T any](t *T) Value[T]

Dereferences converts a pointer into an optional value of the referenced type. Nil pointers become empty values, else the pointer's dereferenced value is wrapped.

Example (Nil)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	var ptr *int

	value := optional.Dereference(ptr)

	fmt.Println(optional.HasItem(value))

}
Output:

false
Example (Nonnil)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	s := "Hello!"

	value := optional.Dereference(&s)

	if item, ok := optional.GetItem(value); ok {
		fmt.Println(item)
	}

}
Output:

Hello!

func FromOKResult added in v1.1.0

func FromOKResult[Item any](item Item, ok bool) Value[Item]

FromOKResult wraps the result of a function that returns an Item and a boolean to indicate whether it returned a value. Returns an empty value if ok is false, else wraps item. Does not check for zero values, so a (nil, true) return value would result in a non-empty result.

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	// f stands in for functions that return a value and a boolean to indicate whether the
	// return value is meaningful, e.g. os.LookupEnv or strings.CutPrefix.
	f := func(s string, ok bool) (string, bool) {
		return s, ok
	}

	optional.
		FromOKResult(f("Hello, world!", true)).
		Invoke(
			func(s string) {
				fmt.Println(s)
			},
		)

	optional.
		FromOKResult(f("none", false)).
		Invoke(
			func(s string) {
				fmt.Println(s)
			},
		)

}
Output:

Hello, world!

func MapItem

func MapItem[Key comparable, Item any](m map[Key]Item, key Key) Value[Item]

MapItem takes a map and a key, returning an empty value if that key does not exist in the map, and the corresponding item for that key otherwise. Only checks whether a map key exists and may happily wrap zero values (e.g. nil pointers).

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	messages := map[string]string{
		"departure": "Goodbye!",
	}

	optional.
		MapItem(messages, "departure").
		Invoke(
			func(s string) {
				fmt.Println(s)
			},
		)

	fmt.Println(
		optional.IsEmpty(
			optional.MapItem(messages, "arrival"),
		),
	)

}
Output:

Goodbye!
true

func NewEmpty

func NewEmpty[T any]() Value[T]

NewEmpty creates an empty optional value. The returned value is immutable, i.e. cannot be changed to contain a value.

func NewWithItem

func NewWithItem[T any](t T) Value[T]

NewWithItem creates an optional value that actually wraps an item. The returned value is immutable, i.e. cannot be changed to wrap a different value or no value at all.

func Pointer

func Pointer[T any](t *T) Value[*T]

Pointer wraps a pointer into an optional value. nil pointers become empty values, else a value containing an item is returned.

Example (Nil)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	var ptr *int

	value := optional.Pointer(ptr)

	fmt.Println(optional.HasItem(value))

}
Output:

false
Example (Nonnil)
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	s := "Hello!"

	value := optional.Pointer(&s)

	if item, ok := optional.GetItem(value); ok {
		fmt.Println(*item)
	}

}
Output:

Hello!

func SliceItem

func SliceItem[Item any](s []Item, index int) Value[Item]

SliceItem takes a slice and an index, returning an empty value if the index is out of bounds for the slice, and the corresponding item for that index otherwise. Only checks whether the index is in range and may happily wrap zero values (e.g. nil pointers).

Example
package main

import (
	"fmt"

	"github.com/GodsBoss/g/optional"
)

func main() {
	items := []string{
		"foo",
		"bar",
		"baz",
	}

	optional.
		SliceItem(items, 1).
		Invoke(
			func(s string) {
				fmt.Println(s)
			},
		)

	fmt.Println(
		optional.IsEmpty(
			optional.SliceItem(items, -1),
		),
	)

	fmt.Println(
		optional.IsEmpty(
			optional.SliceItem(items, 8),
		),
	)

}
Output:

bar
true
true

Directories

Path Synopsis
encoding

Jump to

Keyboard shortcuts

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