optic

package module
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 23 Imported by: 0

README

Go-optics. Modifying immutable data types in Go.

Go-optics provides tooling and functions to modify deeply nested immutable data structures in go.

//Create a nested immutable data structure.
data := NewBlogPost(
    "BlogPost",
    []Comment{
        NewComment("First Comment", "First comment content"),
        NewComment("Second Comment", "Second comment content"),
    },
)

//Create an optic to focus the first comments content.
optic := O.BlogPost().Comments().Nth(0).Content()

//Set a new value to the focused comment.
newData := MustSet(
    optic,
    "Updated comment content",
    data,
)

fmt.Println(newData)

Check out the documentation here go-optics

There are example programs in the examples directory.

The makelens tool which generates optics for your structs is available in the cmd directory.

Documentation

Overview

Package optic implements functional optics for querying and manipulating immutable data structures.

Optics are formed by mixing the following 3 properties

The following optics are provided

Each optic is available in 4 varieties. The basic constructors listed above create optics that are

  • Pure i.e. not able to return errors
  • Non indexed i.e. no index values are provided in the results
  • Non polymorphic i.e. the input types are identical to the output types)

Additional constructors are suffixed with

  • R for impure,non indexed and non polymorphic
  • I for pure, indexed and non polymorphic
  • P for pure, non indexed and polymorphic
  • F for impure, indexed and polymorphic

Optics typically have 8 type paramaters. I,S,T,A,B,RET,RW,DIR

I is the index type. optics focusing on elements of a slice have an int index. optics focusing on elements of a map have the same index type as the map key. optics focusing on elements without a natural index type use the Void type

S is the source type. This is the type of the value that will be passed as input to an optic.

T is the result type. This is the type of the value returned by modification actions. For non polymorphic optics the return type is the same as the source type S

A is the focus type. This is the type of value focused by the optic.

B is the result focus type. This is the type of the value that will be embedded in the result type. For non polymorphic optics the return type is the same as the focus type A

RET is the return type. This indicates if the optic returns a single value like a lens ReturnOne or multiple values like a traversal ReturnMany

RW is the read write type. This indicates if the optic can be written to ReadWrite or only read from ReadOnly

DIR is the direction type. This indicates if the optic can be reversed BiDir or is one way UniDir

Optics can be combined using the provided combinators like

  • Compose which chains optics together.
  • Filtered which filters the values focused by an optic.

Optics can be used to both query and update a data structure using the provided actions (e.g. [ToListOf],Modify). Modification actions do not alter the original data structure instead a new modified copy is returned. Actions are available in 4 varieties

  • standard: The action has a simple verb as a name and is able to return errors. e.g. Modify
  • indexed: The action name is prefixed with an I and is able to return errors. e.g. ModifyI
  • must: The action name is prefixed with Must and will panic on error. e.g. MustModify
  • must indexed: The action name is prefixed with MustI and will panic on error. e.g. MustModifyI

The Optic package also enables external packages to implement efficient combinators and actions by provided access to the low level optic function definitions via the Optic interface. The [Optic.AsExpr] method provides access to the internal expression tree representation of the optic. This can be used to transform optics to queries for external systems e.g. Sql.

Index

Examples

Constants

View Source
const (
	EditInsert     = EditType(expr.EditInsert)
	EditDelete     = EditType(expr.EditDelete)
	EditSubstitute = EditType(expr.EditSubstitute)
	EditTranspose  = EditType(expr.EditTranspose)

	EditLevenshtein = EditType(EditInsert | EditDelete | EditSubstitute)
	EditOSA         = EditType(EditLevenshtein | EditTranspose)
	EditLCS         = EditType(EditInsert | EditDelete)

	EditAny = EditType(0xFF)
)

Variables

View Source
var DisableOpticTypeOptimizations = false
View Source
var ErrDuplicateKey = errors.New("duplicate key")
View Source
var ErrEmptyGet = errors.New("empty getter result")
View Source
var ErrNilPointer = errors.New("nil pointer passed to MustPtrFieldLens")
View Source
var ErrOptionNone = errors.New("none passed to SomeE / SomeEP")
View Source
var ErrPtrNil = errors.New("nil passed to TraversePtrE / TraversePtrEP")
View Source
var ErrUnsafeMissingElement = errors.New("not enough elements were supplied")
View Source
var ErrVariableNotDefined = errors.New("variable not defined")
View Source
var UnsupportedOpticMethod = errors.New("unsupported optic method")

Functions

func Case

func Case[I, S, T, A, B, RET, RW, DIR, ERR, ERRP any](
	condition Predicate[S, ERRP],
	optic Optic[I, S, T, A, B, RET, RW, DIR, ERR],
) switchCase[I, S, T, A, B, RET, RW, DIR, ERR, ERRP]

func Get

func Get[I, S, T, A, B any, RET TReturnOne, RO any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (A, error)

The Get action returns the single focus of the given optic.

Get only accepts optics that return a single value ReturnOne.

See:

Example
data := lo.T2("alpha", "2")

//This optic focuses the A element of a tuple
optic := T2A[string, string]()

viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

//This optic focuses the A element of a tuple and converts it to an int
composedOptic := Compose(T2A[string, string](), ParseInt[int](10, 32))

_, err = Get(composedOptic, data)
fmt.Println(err)
Output:

alpha <nil>
strconv.ParseInt: parsing "alpha": invalid syntax
optic error path:
	ParseInt(10,32)
	TupleElement(0)

func GetContext

func GetContext[I, S, T, A, B any, RET TReturnOne, RO any, DIR any, ERR any](ctx context.Context, o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (A, error)

The GetContext action returns the single focus of the given optic.

GetContext only accepts optics that return a single value ReturnOne. For a version the accepts any optic see GetFirstContext

See:

Example
data := lo.T2("alpha", "2")

//This optic focuses the A element of a tuple
optic := T2A[string, string]()

ctx, cancel := context.WithCancel(context.Background())

viewResult, err := GetContext(ctx, optic, data)
fmt.Println(viewResult, err)

cancel()

_, err = GetContext(ctx, optic, data)
fmt.Println(err)
Output:

alpha <nil>
context canceled
optic error path:
	TupleElement(0)

func GetContextI

func GetContextI[I, S, A any, RET TReturnOne, RO any, DIR any, ERR any](ctx context.Context, o OpticRO[I, S, A, RET, RO, DIR, ERR], source S) (I, A, error)

The GetContextI action returns the single index and focus of the given optic.

GetContextI only accepts optics that return a single value ReturnOne. For a version the accepts any optic see GetFirstContextI

See:

Example
data := map[int]string{
	10: "alpha",
	20: "beta",
	30: "gamma",
	40: "delta",
}

optic := AtMap[int, string](30)

ctx, cancel := context.WithCancel(context.Background())

var index int
var viewResult mo.Option[string]
var err error
index, viewResult, err = GetContextI(ctx, optic, data)
fmt.Println(index, viewResult, err)

cancel()

_, _, err = GetContextI(ctx, optic, data)
fmt.Println(err)
Output:

30 {true gamma} <nil>
context canceled
optic error path:
	Const(30)
	IgnoreWrite(Const[map[int]string](30))
	TupleOf(Identity , IgnoreWrite(Const[map[int]string](30)))

func GetFirst

func GetFirst[I, S, T, A, B, RET any, RO, DIR, ERR any](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (A, bool, error)

The GetFirst action returns the first focus of the optic or false if there are no elements.

See:

Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := TraverseSlice[string]()

viewResult, found, err := GetFirst(optic, data)
fmt.Println(viewResult, found, err)

_, found, err = GetFirst(optic, []string{})
fmt.Println(found, err)
Output:

alpha true <nil>
false <nil>

func GetFirstContext

func GetFirstContext[I, S, T, A, B, RET any, RO, DIR any, ERR any](ctx context.Context, o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (A, bool, error)

The GetFirstContext action returns the first focus of the optic or false if there are no elements.

See:

Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := TraverseSlice[string]()

ctx, cancel := context.WithCancel(context.Background())

viewResult, found, err := GetFirstContext(ctx, optic, data)
fmt.Println(viewResult, found, err)

cancel()

_, _, err = GetFirstContext(ctx, optic, data)
fmt.Println(err)
Output:

alpha true <nil>
context canceled
optic error path:
	Traverse

func GetFirstContextI

func GetFirstContextI[I, S, T, A, B, RET any, RO any, DIR any, ERR any](ctx context.Context, o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (I, A, bool, error)

The GetFirstContextI action returns the first focus and index of the optic or false if there are no elements.

See:

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := TraverseMap[string, int]()

ctx, cancel := context.WithCancel(context.Background())

index, viewResult, found, err := GetFirstContextI(ctx, optic, data)
fmt.Println(index, viewResult, found, err)

cancel()

_, _, err = GetFirstContext(ctx, optic, data)
fmt.Println(err)
Output:

alpha 1 true <nil>
context canceled
optic error path:
	Traverse

func GetFirstI

func GetFirstI[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S) (I, A, bool, error)

The GetFirstI action returns the first focus and index of the optic or false if there are no elements.

See:

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := TraverseMap[string, int]()

index, viewResult, found, err := GetFirstI(optic, data)
fmt.Println(index, viewResult, found, err)

_, found, err = GetFirst(optic, map[string]int{})
fmt.Println(found, err)
Output:

alpha 1 true <nil>
false <nil>

func GetI

func GetI[I, S, A any, RET TReturnOne, RO any, DIR any, ERR any](o OpticRO[I, S, A, RET, RO, DIR, ERR], source S) (I, A, error)

The GetI action returns the single indexed focus of the given optic.

GetI only accepts optics that return a single value ReturnOne.

See:

Example
data := map[int]string{
	10: "alpha",
	20: "beta",
	30: "gamma",
	40: "delta",
}

optic := AtMap[int, string](30)

var index int
var viewResult mo.Option[string]
var err error
index, viewResult, err = GetI(optic, data)
fmt.Println(index, viewResult, err)
Output:

30 {true gamma} <nil>

func IncCustomMetric

func IncCustomMetric(ctx context.Context, name string, val int)

IncCustomMetric increments the given custom metric contained within the context. Custom metrics will bubble up to the nearest [WithMetric] optic.

Example
traverseIntSlice := TraversalE[[]int, int](
	func(ctx context.Context, source []int) iter.Seq2[int, error] {
		return func(yield func(int, error) bool) {
			focusCount := 0
			for _, v := range source {
				focusCount++
				if !yield(v, nil) {
					break
				}
			}
			IncCustomMetric(ctx, "custom", focusCount)
		}
	},
	func(ctx context.Context, source []int) (int, error) {
		return len(source), nil
	},
	func(ctx context.Context, fmap func(focus int) (int, error), source []int) ([]int, error) {

		focusCount := 0

		ret := make([]int, 0, len(source))
		for _, oldVal := range source {
			focusCount++
			newVal, err := fmap(oldVal)
			if err != nil {
				IncCustomMetric(ctx, "custom", focusCount)
				return nil, err
			}
			ret = append(ret, newVal)
		}
		IncCustomMetric(ctx, "custom", focusCount)
		return ret, nil
	},
	ExprCustom("ExampleIncCustomMetric"),
)

data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var metrics Metrics

result, err := Modify(WithMetrics(traverseIntSlice, &metrics), Mul(2), data)
fmt.Println(result, err)
fmt.Println(metrics)
Output:

[2 4 6 8 10 12 14 16 18 20] <nil>
metrics[F:10 A:1 I:0 L:0 Custom:map[custom:10]]

func IxMatchComparable

func IxMatchComparable[I comparable]() func(indexA, indexB I) bool

func IxMatchDeep

func IxMatchDeep[I any]() func(indexA, indexB I) bool

func IxMatchVoid

func IxMatchVoid() func(indexA, indexB Void) bool

func JoinCtxErr

func JoinCtxErr(ctx context.Context, err error) error

JoinCtxErr returns the given error joined with ctx.Err()

This function is intended to be used in custom action implementations to enable the reporting of deadline exceeded errors.

func Modify

func Modify[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, RETF TReturnOne, ERR, ERRFMAP any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], op Operation[A, B, RETF, ERRFMAP], source S) (T, error)

The Modify action modifies the source by applying the given operator to every focus.

See:

  • ModifyCheck for a version that reports if the input optic focused no elements
  • ModifyI for an index aware version.
  • ModifyContext for a context aware version.
  • MustModify for a version that panics on error.
Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice parsed as an int
optic := Compose(TraverseSlice[string](), ParseInt[int](10, 32))

var result []string
var err error
//Note the operation works on an int but the result is a new []string with the applied modifications
result, err = Modify(optic, Add[int](1), data)
fmt.Println(result, err)

//When an error is encountered the Over action short circuits and returns the error.
errData := []string{"1", "two", "3", "4"}
_, err = Modify(optic, Add[int](1), errData)
fmt.Println(err)
Output:

[2 3 4 5] <nil>
strconv.ParseInt: parsing "two": invalid syntax
optic error path:
	ParseInt(10,32)
	Traverse

func ModifyCheck

func ModifyCheck[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRFMAP any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap Operation[A, B, FRET, ERRFMAP], source S) (T, bool, error)

The ModifyCheck action modifies the source by applying the given operator to every focus returning false if the input optic focused no elements

See:

Example
data := []int{1, 2, 3, 4}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

var result []int
var modified bool
var err error

result, modified, err = ModifyCheck(optic, Add[int](1), data)
fmt.Println(result, modified, err)

//When no elements are focused false is returned for modified
emptyData := []int{}
_, modified, _ = ModifyCheck(optic, Add[int](1), emptyData)
fmt.Println(modified)
Output:

[2 3 4 5] true <nil>
false

func ModifyCheckContext

func ModifyCheckContext[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRFMAP any](ctx context.Context, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap Operation[A, B, FRET, ERRFMAP], source S) (T, bool, error)

The ModifyCheckContext action modifies the source by applying the given operator to every focus returning false if the input optic focused no elements.

See:

Example
data := []int{1, 2, 3, 4}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

ctx, cancel := context.WithCancel(context.Background())

var result []int
var modified bool
var err error

result, modified, err = ModifyCheckContext(ctx, optic, Add[int](1), data)
fmt.Println(result, modified, err)

cancel()

_, _, err = ModifyCheckContext(ctx, optic, Add[int](1), data)
fmt.Println(err)
Output:

[2 3 4 5] true <nil>
context canceled
optic error path:
	ValueI[int,int].value
	Traverse

func ModifyCheckContextI

func ModifyCheckContextI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRF any](ctx context.Context, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap OperationI[I, A, B, FRET, ERRF], source S) (T, bool, error)

The ModifyCheckContextI action modifies the source by applying the given indexed operator to every focus.

See:

Example
data := []int{1, 2, 3, 4}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

ctx, cancel := context.WithCancel(context.Background())

var result []int
var modified bool
var err error

result, modified, err = ModifyCheckContextI(ctx, optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result, modified, err)

cancel()

_, _, err = ModifyCheckContextI(ctx, optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(err)
Output:

[10 2 30 4] true <nil>
context canceled
optic error path:
	func2
	Traverse

func ModifyCheckI

func ModifyCheckI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRF any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap OperationI[I, A, B, FRET, ERRF], source S) (T, bool, error)

The ModifyCheckI action modifies the source by applying the given indexed operator to every focus returning false if the input optic focused no elements

See:

Example
data := []int{1, 2, 3, 4}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

var result []int
var modified bool
var err error

result, modified, err = ModifyCheckI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result, modified, err)

//When no elements are focused false is returned for modified
emptyData := []int{}
_, modified, _ = ModifyCheckI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), emptyData)
fmt.Println(modified)
Output:

[10 2 30 4] true <nil>
false

func ModifyContext

func ModifyContext[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRFMAP any](ctx context.Context, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], f Operation[A, B, FRET, ERRFMAP], source S) (T, error)

The ModifyContext action modifies the source by applying the given operator to every focus.

See:

Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice parsed as an int
optic := Compose(TraverseSlice[string](), ParseInt[int](10, 32))

ctx, cancel := context.WithCancel(context.Background())

var result []string
var err error
//Note the operation works on an int but the result is a new []string with the applied modifications
result, err = ModifyContext(ctx, optic, Add[int](1), data)
fmt.Println(result, err)

cancel()

_, err = ModifyContext(ctx, optic, Add[int](1), data)
fmt.Println(err)
Output:

[2 3 4 5] <nil>
context canceled
optic error path:
	ParseInt(10,32)
	Traverse

func ModifyContextI

func ModifyContextI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR any, ERRFMAP any](ctx context.Context, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], f OperationI[I, A, B, FRET, ERRFMAP], source S) (T, error)

The ModifyContextI action modifies the source by applying the given indexed operator to every focus.

See:

Example
data := []int{1, 2, 3, 4}

optic := TraverseSlice[int]()

ctx, cancel := context.WithCancel(context.Background())

var result []int
var err error
result, err = ModifyContextI(ctx, optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result, err)

cancel()

_, err = ModifyContextI(ctx, optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(err)
Output:

[10 2 30 4] <nil>
context canceled
optic error path:
	func2
	Traverse

func ModifyI

func ModifyI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, RETF TReturnOne, ERR any, ERRFMAP any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], f OperationI[I, A, B, RETF, ERRFMAP], source S) (T, error)

The ModifyI action modifies the source by applying the given indexed operator to every focus.

See:

Example
data := []int{1, 2, 3, 4}

optic := TraverseSlice[int]()

var result []int
var err error
result, err = ModifyI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result, err)
Output:

[10 2 30 4] <nil>

func Must

func Must[T any](t T, err error) T

Must panics if err != nil

func Must2

func Must2[T any, T2 any](t T, t2 T2, err error) (T, T2)

Must2 panics if err != nil

func Must2I

func Must2I[I, T, T2 any](i I, val T, val2 T2, err error) (I, T, T2)

Must2I panics if err != nil

func MustGet

func MustGet[I, S, T, A, B any, RET TReturnOne, RO any, DIR any, ERR TPure](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) A

The MustGet action returns the single focus of the given optic and panics on error.

MustGet only accepts optics that return a single value ReturnOne. For a version the accepts any optic see MustGetFirst

See:

Example
data := lo.T2("alpha", "2")

//This optic focuses the A element of a tuple
optic := T2A[string, string]()

viewResult := MustGet(optic, data)
fmt.Println(viewResult)
Output:

alpha

func MustGetFirst

func MustGetFirst[I, S, T, A, B, RET any, RO, DIR any, ERR TPure](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], source S) (A, bool)

The MustGetFirst action returns the first focus of the optic or false if there are no elements.

See:

  • [IMustPreView] for an index aware version.
  • GetFirst for a non context aware version.
  • GetFirstContext for a context aware version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := TraverseSlice[string]()

viewResult, found := MustGetFirst(optic, data)
fmt.Println(viewResult, found)

_, found = MustGetFirst(optic, []string{})
fmt.Println(found)
Output:

alpha true
false

func MustGetFirstI

func MustGetFirstI[I, S, T, A, B, RET, RW, DIR any, ERR TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S) (I, A, bool)

The MustGetFirstI action returns the first focus and index of the optic or false if there are no elements.

See:

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := TraverseMap[string, int]()

index, viewResult, found := MustGetFirstI(optic, data)
fmt.Println(index, viewResult, found)

_, _, found = MustGetFirstI(optic, map[string]int{})
fmt.Println(found)
Output:

alpha 1 true
false

func MustGetI

func MustGetI[I, S, A any, RET TReturnOne, RO any, DIR any, ERR TPure](o OpticRO[I, S, A, RET, RO, DIR, ERR], source S) (I, A)

The IMustGet action returns the single index and focus of the given optic and panics on error.

IMustGet only accepts optics that return a single value ReturnOne. For a version the accepts any optic see [IMustGetFirst]

See:

  • [IMustGetFirst] for a version the accepts ReturnMany optics
  • MustGet for a non index aware version.
  • GetI for a non context aware version
  • GetContextI for a context aware version
Example
data := map[int]string{
	10: "alpha",
	20: "beta",
	30: "gamma",
	40: "delta",
}

optic := AtMap[int, string](30)

var index int
var viewResult mo.Option[string]
index, viewResult = MustGetI(optic, data)
fmt.Println(index, viewResult)
Output:

30 {true gamma}

func MustI

func MustI[I, T any](i I, val T, err error) (I, T)

MustI panics if err != nil

func MustModify

func MustModify[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, RETF TReturnOne, ERR, ERRFMAP TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], f Operation[A, B, RETF, ERRFMAP], source S) T

The MustModify action modifies the source by applying the given operator to every focus panicking on error.

See:

  • MustModifyCheck for a version that panics on error.
  • [IMustOver] for an index aware version.
  • Modify for a non context aware version.
  • ModifyContext for a context aware version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice.
optic := TraverseSlice[string]()

//Note the operation works on an int but the result is a new []string with the applied modifications
var result []string = MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(result)
Output:

[ALPHA BETA GAMMA DELTA]

func MustModifyCheck

func MustModifyCheck[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRFMAP TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap Operation[A, B, FRET, ERRFMAP], source S) (T, bool)

The MustModifyCheck action modifies the source by applying the given operator to every focus panicking on error and returning false if the input optic focused no elements

See:

  • MustModify for a version that does not report if the input optic focused no elements
  • [IMustFailOver] for an index aware version.
  • ModifyCheck for a non context aware version.
  • ModifyCheckContext for a context aware version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice.
optic := TraverseSlice[string]()

var result []string
var modified bool
result, modified = MustModifyCheck(optic, Op(strings.ToUpper), data)
fmt.Println(result, modified)

_, modified = MustModifyCheck(optic, Op(strings.ToUpper), []string{})
fmt.Println(modified)
Output:

[ALPHA BETA GAMMA DELTA] true
false

func MustModifyCheckI

func MustModifyCheckI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR, ERRF TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap OperationI[I, A, B, FRET, ERRF], source S) (T, bool)

The IMustFailOver action modifies the source by applying the given indexed operator to every focus panicking on error.

See:

Example
data := []int{1, 2, 3, 4}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

var result []int
var modified bool
result, modified = MustModifyCheckI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result, modified)

_, modified = MustModifyCheckI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), []int{})
fmt.Println(modified)
Output:

[10 2 30 4] true
false

func MustModifyI

func MustModifyI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, FRET TReturnOne, ERR TPure, ERRFMAP TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], f OperationI[I, A, B, FRET, ERRFMAP], source S) T

The MustModifyI action modifies the source by applying the given indexed operator to every focus panicking on error.

See:

Example
data := []int{1, 2, 3, 4}

optic := TraverseSlice[int]()

var result []int = MustModifyI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	} else {
		return focus
	}
}), data)
fmt.Println(result)
Output:

[10 2 30 4]

func MustReverseGet

func MustReverseGet[I, S, T, A, B, RET any, RO any, DIR TBiDir, ERR TPure](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], focus B) T

The MustReverseGet action retrieves the single reverse get focus of the given optic and panics on error

See:

Example
optic := Mul(10)

//ReView runs the optic "backwards" in this case dividing by 10.
var result int = MustReverseGet(optic, 10)
fmt.Println(result)
Output:

1

func MustSet

func MustSet[I, S, T, A, B, RET any, RW TReadWrite, DIR any, ERR TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], val B, source S) T

The MustSet action sets the focused elements of the optic to the given value and panics on error

See:

  • MustModify for a version that applies a mapping function to each focus.
  • Set for a non context aware version.
  • SetContext for a context aware version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice.
optic := TraverseSlice[string]()

var result []string = MustSet(optic, "epsilon", data)
fmt.Println(result)
Output:

[epsilon epsilon epsilon epsilon]

func OpticError

func OpticError(err error, expression func() expr.OpticExpression) error

OpticError adds the given optic expression to the error if the error is != nil

This should only be called from within an Omni optic when writing custom combinators.

func PredGet

func PredGet[S any](ctx context.Context, fnc PredicateE[S], source S) (bool, error)

PredGet gets the predicate value from an Operation or OperationI defaulting to false if no value is found.

Example
res, err := PredGet(context.Background(), Gt(3), 7)
fmt.Println(res, err)

//PredGet converts an empty result to false
res, err = PredGet(
	context.Background(),
	Compose(
		First(
			TraverseSlice[int](),
		),
		Gt(3),
	),
	[]int{},
)
fmt.Println(res, err)
Output:

true <nil>
false <nil>

func PredGetI

func PredGetI[I, S, ERR any](ctx context.Context, fnc PredicateI[I, S, ERR], source S, index I) (bool, error)

func PredToIxMatch

func PredToIxMatch[I any, ERR TPure](ixMatch Predicate[lo.Tuple2[I, I], ERR]) func(a, b I) bool

func PullE

func PullE[I, A any](iterFnc SeqE[A]) (next func() (focus A, ok bool, err error), stop func())

PullE converts the “push-style” SeqI into a “pull-style” iterator accessed by the two functions next and stop.

See iter.Pull2 for more documentation.

func PullI

func PullI[I, A any](iterFnc SeqI[I, A]) (next func() (index I, focus A, ok bool), stop func())

PullI converts the “push-style” SeqI into a “pull-style” iterator accessed by the two functions next and stop.

See iter.Pull2 for more documentation.

func PullIE

func PullIE[I, A any](iterFnc SeqIE[I, A]) (next func() (index I, focus A, err error, ok bool), stop func())

PullIE converts the “push-style” SeqIE into a “pull-style” iterator accessed by the two functions next and stop.

See iter.Pull for more documentation.

func ReverseGet

func ReverseGet[I, S, T, A, B any, RET any, RO any, DIR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RO, DIR, ERR], focus B) (T, error)

The ReverseGet action retrieves the single reverse get focus of the given optic.

See:

Example
optic := ParseInt[int](10, 32)

var err error
var result string

//ReView runs the optic "backwards" in this case converting an int back to a string.
result, err = ReverseGet(optic, 1)
fmt.Println(result, err)
Output:

1 <nil>

func ReverseGetContext

func ReverseGetContext[I, S, T, A, B any, RET any, RO any, DIR TBiDir, ERR any](ctx context.Context, o Optic[I, S, T, A, B, RET, RO, DIR, ERR], focus B) (T, error)

The ReverseGetContext action retrieves the single reverse get focus of the given optic.

See:

Example
optic := ParseInt[int](10, 32)

ctx, cancel := context.WithCancel(context.Background())

var err error
var result string

//ReView runs the optic "backwards" in this case converting an int back to a string.
result, err = ReverseGetContext(ctx, optic, 1)
fmt.Println(result, err)

cancel()

_, err = ReverseGetContext(ctx, optic, 1)
fmt.Println(err)
Output:

1 <nil>
context canceled
optic error path:
	ParseInt(10,32)

func Set

func Set[I, S, T, A, B, RET any, RW TReadWrite, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], val B, source S) (T, error)

The Set action sets the focused elements of the optic to the given value.

See:

  • Modify for a version that applies a mapping function to each focus.
  • SetContext for a context aware version.
  • MustSet for a version that panics on error.
Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice parsed as an int
optic := Compose(TraverseSlice[string](), ParseInt[int](10, 32))

var result []string
var err error
//Note the operation works on an int but the result is a new []string with the applied modifications
result, err = Set(optic, 100, data)
fmt.Println(result, err)

//Set does not need to parse the existing value so is able to update values that
//would cause an error when using the over action.
errData := []string{"1", "two", "3", "4"}
result, err = Set(optic, 100, errData)
fmt.Println(result, err)
Output:

[100 100 100 100] <nil>
[100 100 100 100] <nil>

func SetContext

func SetContext[I, S, T, A, B any, RET any, RW TReadWrite, DIR, ERR any](ctx context.Context, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], val B, source S) (T, error)

The SetContext action sets the focused elements of the optic to the given value.

See:

  • ModifyContext for a version that applies a mapping function to each focus.
  • Set for a non context aware version.
  • MustSet for a version that panics on error.
Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice parsed as an int
optic := Compose(TraverseSlice[string](), ParseInt[int](10, 32))

ctx, cancel := context.WithCancel(context.Background())

var result []string
var err error
//Note the operation works on an int but the result is a new []string with the applied modifications
result, err = SetContext(ctx, optic, 100, data)
fmt.Println(result, err)

cancel()

_, err = SetContext(ctx, optic, 100, data)
fmt.Println(err)
Output:

[100 100 100 100] <nil>
context canceled
optic error path:
	ParseInt(10,32)
	Traverse

func ValidateOptic

func ValidateOptic[I any, S comparable, A any, RET any, RW, DIR, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], source S, newValue A) error

func ValidateOpticFuzz

func ValidateOpticFuzz[I any, S comparable, A any, RET any, RW, DIR, ERR any, PERR TPure](f *testing.F, o Optic[I, S, S, A, A, RET, RW, DIR, ERR])

func ValidateOpticP

func ValidateOpticP[I any, S comparable, T, A, B any, RET any, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S, newValue A, aToB func(A) B, tToS func(T) S) error

func ValidateOpticPred

func ValidateOpticPred[I, S, A any, RET any, RW, DIR, ERR any, PERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], source S, newValue A, eq Predicate[lo.Tuple2[S, S], PERR]) error

func ValidateOpticPredP

func ValidateOpticPredP[I any, S, T, A, B any, RET any, RW, DIR, ERR any, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S, newValue A, aToB func(A) B, tToS func(T) S, eq Predicate[lo.Tuple2[S, S], PERR]) error

func ValidateOpticTest

func ValidateOpticTest[I any, S comparable, A any, RET any, RW, DIR, ERR any](t *testing.T, o Optic[I, S, S, A, A, RET, RW, DIR, ERR], source S, newValue A)

func ValidateOpticTestP

func ValidateOpticTestP[I any, S comparable, T, A, B any, RET any, RW, DIR, ERR any](t *testing.T, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S, newValue A, aToB func(A) B, tToS func(T) S)

func ValidateOpticTestPred

func ValidateOpticTestPred[I, S, A any, RET any, RW, DIR, ERR any, PERR any](t *testing.T, o Optic[I, S, S, A, A, RET, RW, DIR, ERR], source S, newValue A, eq Predicate[lo.Tuple2[S, S], PERR])

func ValidateOpticTestPredP

func ValidateOpticTestPredP[I, S, T, A, B any, RET any, RW, DIR, ERR any, PERR any](t *testing.T, o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S, newValue A, aToB func(A) B, tToS func(T) S, eq Predicate[lo.Tuple2[S, S], PERR])

Types

type Arithmetic

type Arithmetic interface {
	constraints.Complex | Real
}

Type constraint for types than be operated on by basic arithmetic operations like +,-./,* This type constraint includes the complex types. See Real for a type constraint without complex types.

type BiDir

type BiDir Void

Indicates this optic supports reverseget

type ChosenSide

type ChosenSide bool
const (
	//Indicates the [Chosen] was left.
	ChosenLeft ChosenSide = false
	//Indicates the [Chosen] was right.
	ChosenRight ChosenSide = true
)

type Collection

type Collection[I, A, ERR any] interface {
	//Equals[Collection[I, A, ERR]]
	//EqualsAny
	AsIter() func(ctx context.Context) SeqIE[I, A]
	AsIxGet() func(ctx context.Context, index I) SeqIE[I, A]
	AsIxMatch() func(a, b I) bool
	AsLengthGetter() func(ctx context.Context) (int, error)
	ErrType() ERR
	AsExpr() expr.SeqExpr
	String() string
}

Collection represents a container of multiple indexed values.

func Col

func Col[A any](
	seq iter.Seq[A],
	lengthGetter func() int,
) Collection[int, A, Pure]

Constructor for a non index aware pure Collection

An int index is generated automatically.

See:

  • ColIE for an index aware impure version.
  • ColE for an impure version.
  • ColI for an index aware pure version.
  • ValCol for a varargs/slice based version.

If any of the given functions are nil then a default implementation will be provided.

Example
data := []string{"alpha", "beta", "gamma"}

col := Col[string](
	func(yield func(string) bool) {
		for _, v := range data {
			if !yield(v) {
				break
			}
		}
	},
	func() int {
		return len(data)
	},
)

optic := TraverseCol[int, string]()

res, ok := MustGetFirst(Index(optic, 1), col)
fmt.Println("Result:", res, ok)

res, ok = MustGetFirst(Index(optic, 10), col)
fmt.Println("Result:", res, ok)
Output:

Result: beta true
Result:  false

func ColE

func ColE[A any](
	seq func(ctx context.Context) SeqE[A],
	lengthGetter func(ctx context.Context) (int, error),
) Collection[int, A, Err]

Constructor for an impure Collection

See:

  • ColIE for an index aware impure version.
  • ColI for an index aware pure version.
  • Col for a non index aware pure version.
  • ValColE for a varargs/slice based version.

If any of the given functions are nil then a default implementation will be provided.

Example
data := []string{"alpha", "beta", "gamma"}

col := ColE[string](
	func(ctx context.Context) SeqE[string] {
		return func(yield func(ValueE[string]) bool) {
			for _, v := range data {
				if !yield(ValE(v, nil)) {
					break
				}
			}
		}
	},
	func(ctx context.Context) (int, error) {
		return len(data), nil
	},
)

optic := TraverseColE[int, string, Err]()

res, ok, err := GetFirst(Index(optic, 1), col)
fmt.Println("Result:", res, ok, err)

res, ok, err = GetFirst(Index(optic, 10), col)
fmt.Println("Result:", res, ok, err)
Output:

Result: beta true <nil>
Result:  false <nil>

func ColErr

func ColErr[I, A any, ERR any](s Collection[I, A, ERR]) Collection[I, A, Err]

ColErr modifies any [Collection]s to Err

Example
data := ValCol("2", "3", "3")

//The Sort may generate an error in the collection during sorting.
//The Collection has a CompositionTree asit's ERR.
sort := OrderedCol[int](
	OrderBy(
		Compose(
			ParseInt[int](10, 0),
			Negate[int](),
		),
	),
)

//Simplify the error composition tree in the collection.
sortErr := ColSourceFocusErr(sort)

//res, err := Modify(
//	Identity[Collection[int, string, Err]](),
//	sort, //<----- Compile error here, The error composition tree in sort is not compatible with filteredErr.
//	ColErr(data),
//)

res, err := Modify(
	Identity[Collection[int, string, Err]](),
	sortErr,
	ColErr(data),
)

fmt.Println(res, err)
Output:

Col[1:3 2:3 0:2] <nil>

func ColI

func ColI[I, A any](
	seq iter.Seq2[I, A],
	ixget func(index I) iter.Seq2[I, A],
	ixMatch func(a, b I) bool,
	lengthGetter func() int,
) Collection[I, A, Pure]

Constructor for an impure Collection

See:

  • ColIE for an index aware impure version.
  • ColE for an impure version.
  • Col for a non index aware pure version.
  • ValColI for a varargs/slice based version.

If any of the given functions are nil then a default implementation will be provided.

Example
data := []string{"alpha", "beta", "gamma"}

col := ColI[int, string](
	func(yield func(int, string) bool) {
		for i, v := range data {
			if !yield(i, v) {
				break
			}
		}
	},
	func(index int) iter.Seq2[int, string] {
		return func(yield func(int, string) bool) {
			if index < 0 || index >= len(data) {
				return
			}

			yield(index, data[index])
		}

	},
	IxMatchComparable[int](),
	func() int {
		return len(data)
	},
)

optic := TraverseCol[int, string]()

res, ok := MustGetFirst(Index(optic, 1), col)
fmt.Println("Result:", res, ok)

res, ok = MustGetFirst(Index(optic, 10), col)
fmt.Println("Result:", res, ok)
Output:

Result: beta true
Result:  false

func ColIE

func ColIE[ERR, I, A any](
	seq func(ctx context.Context) SeqIE[I, A],
	ixget func(ctx context.Context, index I) SeqIE[I, A],
	ixMatch func(a, b I) bool,
	lengthGetter func(ctx context.Context) (int, error),
) Collection[I, A, ERR]

Constructor for an index aware impure Collection

See:

  • ColE for a non index aware impure version.
  • ColI for an index aware pure version.
  • Col for a non index aware pure version.
  • ValColIE for a varargs/slice based version.

If any of the given functions are nil then a default implementation will be provided.

Example
data := []string{"alpha", "beta", "gamma"}

col := ColIE[Err, int, string](
	func(ctx context.Context) SeqIE[int, string] {
		return func(yield func(ValueIE[int, string]) bool) {
			for i, v := range data {
				if !yield(ValIE(i, v, nil)) {
					break
				}
			}
		}
	},
	func(ctx context.Context, index int) SeqIE[int, string] {
		return func(yield func(ValueIE[int, string]) bool) {
			if index < 0 || index >= len(data) {
				yield(ValIE(index, "", errors.New("index out of range")))
				return
			}

			yield(ValIE(index, data[index], nil))
		}
	},
	IxMatchComparable[int](),
	func(ctx context.Context) (int, error) {
		return len(data), nil
	},
)

optic := TraverseColE[int, string, Err]()

res, ok, err := GetFirst(Index(optic, 1), col)
fmt.Println("Result:", res, ok, err)

res, ok, err = GetFirst(Index(optic, 10), col)
fmt.Println("Result:", res, ok, err)
Output:

Result: beta true <nil>
Result:  false index out of range
optic error path:
	Traverse
	Index(10)

func ColPure

func ColPure[I, A any, ERR TPure](s Collection[I, A, ERR]) Collection[I, A, Pure]

ColPure modifies a pure Collection to a Collection with an arbitrary ERR type.

func MapCol

func MapCol[K comparable, S any](source map[K]S) Collection[K, S, Pure]

The MapCol function converts a Map to a Collection.

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
}

var result map[string]int = MustModify(
	MapToCol[string, int](),
	AppendCol(
		MapCol(map[string]int{
			"gamma": 3,
			"delta": 4,
		}),
	),
	data,
)

fmt.Println(result)
Output:

map[alpha:1 beta:2 delta:4 gamma:3]

func RangeCol

func RangeCol[A Real](from, to A) Collection[int, A, Pure]

RangeCol return a Collection that yields the values between from and to inclusive.

Example
data := []int{1, 2, 3}

var result []int = MustModify(
	SliceToCol[int](),
	AppendCol(
		RangeCol(4, 10),
	),
	data,
)

fmt.Println(result)

//[1 2 3 4 5 6 7 8 9 10]

func SliceCol

func SliceCol[A any](source []A) Collection[int, A, Pure]

The SliceCol function converts a Slice to a Collection.

func StringCol

func StringCol(source string) Collection[int, rune, Pure]

The StringCol function converts a String to a Collection.

func ValCol

func ValCol[A any](values ...A) Collection[int, A, Pure]

ValCol returns a Collection for the given values with an int index type.

See:

  • ValCol for a version with an arbitrary numeric index type.
  • ValColI for a version with a custom index
  • ValColE for a version with error support
  • ValColIE for a version with custom index and error support
Example
data := []string{
	"alpha",
	"beta",
}

var result []string = MustModify(
	SliceToCol[string](),
	AppendCol(ValCol("gamma", "delta")),
	data,
)

fmt.Println(result)
Output:

[alpha beta gamma delta]

func ValColE

func ValColE[A any](values ...ValueE[A]) Collection[int, A, Err]

ValColE returns a Collection for the given values and erros with an int index type.

See:

  • ValCol for a version with a automatic numeric index type
  • ValColI for a version with a custom index
  • ValColE for a version with error support
  • ValColIE for a version with custom index and error support
Example
data := []string{
	"alpha",
	"beta",
}

s := ValColE[string](
	ValE("gamma", nil),
	ValE("", errors.New("sabotage")),
)

_, err := Modify(
	ColFocusErr(SliceToCol[string]()),
	AppendCol(
		s,
	),
	data,
)

fmt.Println(err)
Output:

sabotage
optic error path:
	ToCol
	ColFocusErr(ToCol(int,[]string,[]string,string,string))

func ValColI

func ValColI[I any, A any](ixMatch func(a, b I) bool, values ...ValueI[I, A]) Collection[I, A, Pure]

ColOfValues returns an Collection for the given index and values

See:

  • ValCol for a version with a automatic numeric index type
  • ValColE for a version with error support
  • ValColIE for a version with custom index and error support
Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
}

var result map[string]int = MustModify(
	MapToCol[string, int](),
	AppendCol(
		ValColI(
			IxMatchComparable[string](),
			ValI("gamma", 3),
			ValI("delta", 4),
		),
	),
	data,
)

fmt.Println(result)
Output:

map[alpha:1 beta:2 delta:4 gamma:3]

func ValColIE

func ValColIE[I any, A, ERR any](ixMatch func(a, b I) bool, values ...ValueIE[I, A]) Collection[I, A, ERR]

ValColIE returns an Collection for the given index,value and errors values.

See:

  • ValCol for a simpler version with an int index
  • ValCol for a version with a automatic numeric index type
  • ValColI for a version with a custom index
  • ValColE for a version with error support
Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
}

_, err := Modify(
	ColFocusErr(MapToCol[string, int]()),
	AppendCol(
		ValColIE[string, int, Err](
			IxMatchComparable[string](),
			ValIE("gamma", 3, nil),
			ValIE("delta", 4, errors.New("sabotage")),
		),
	),
	data,
)

fmt.Println(err)
Output:

sabotage
optic error path:
	ToCol
	ColFocusErr(ToCol(string,map[string]int,map[string]int,int,int))

type CollectionType

type CollectionType[I, S, T, A, B any, ERR any] struct {
	// contains filtered or unexported fields
}

CollectionType contains [Iso]s to convert between Collection and an arbitrary collection type like slice or map. This enables collection operations like FilteredCol,Append and OrderedCol to be applied to any CollectionType type.

func ColType

func ColType[I, S, A any, TRET any, RET TReturnOne, TRW, RW TReadWrite, TDIR any, DIR TBiDir, ERR any](
	toCol Optic[Void, S, S, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR],
	traverse Optic[I, S, S, A, A, TRET, TRW, TDIR, ERR],
) CollectionType[I, S, S, A, A, ERR]

ColType returns a CollectionType using the given Iso to convert to and from a Collection

See:

Example
//To create a custom collection we first need an iso that converts
//from the collection type to a [Collection] and back.
sliceToCol := CombiIso[ReturnOne, ReadWrite, Pure, []string, []string, Collection[int, string, Pure], Collection[int, string, Pure]](
	//convert slice to collection
	func(ctx context.Context, source []string) (Collection[int, string, Pure], error) {
		return ColI(
			func(yield func(index int, focus string) bool) {
				for i, v := range source {
					if !yield(i, v) {
						return
					}
				}
			},
			func(index int) iter.Seq2[int, string] {
				return func(yield func(index int, focus string) bool) {
					yield(index, source[index])
				}
			},
			IxMatchComparable[int](),
			func() int {
				return len(source)
			},
		), nil
	},
	//convert collection to slice
	func(ctx context.Context, focus Collection[int, string, Pure]) ([]string, error) {
		var ret []string
		for val := range focus.AsIter()(ctx) {
			_, focus, focusErr := val.Get()
			if focusErr != nil {
				return nil, focusErr
			}
			ret = append(ret, focus)
		}
		return ret, nil
	},
	ExprCustom("ExampleCol"),
)

//We can now use the iso to create a Collection
sliceCol := ColType(
	sliceToCol,
	TraverseSlice[string](),
)

//We can now convert a col op into a col op for our specific collection

//Optic[Void, []string, []string, []string, []string, ReturnOne, ReadWrite, UniDir]
stringReversed := ColTypeOp(sliceCol, ReversedCol[int, string]())

result := MustGet(stringReversed, []string{"alpha", "beta", "gamma", "delta"})

fmt.Println(result)
Output:

[delta gamma beta alpha]

func ColTypeP

func ColTypeP[I, S, T, A, B any, TRET any, RETI, RETJ TReturnOne, TRW, RWI, RWJ TReadWrite, TDIR any, DIRI, DIRJ TBiDir, ERR any](
	toCol Optic[Void, S, T, Collection[I, A, ERR], Collection[I, B, ERR], RETI, RWI, DIRI, ERR],
	fromColP Optic[Void, Collection[I, A, ERR], Collection[I, B, ERR], S, T, RETJ, RWJ, DIRJ, ERR],
	traverse Optic[I, S, T, A, B, TRET, TRW, TDIR, ERR],
) CollectionType[I, S, T, A, B, ERR]

ColTypeP returns a CollectionType using the given [Iso]s to convert to and from a Collection

See:

  • ColType for a non polymorphic version.
Example
//We can now use the iso to create a Collection
colType := ColTypeP(
	ColFocusErr(SliceToColP[string, int]()),
	ColSourceErr(AsReverseGet(SliceToColP[int, string]())),
	EErr(TraverseSliceP[string, int]()),
)

op := ColOfP(
	EErr(ComposeLeft(
		TraverseColEP[int, string, int, Err](),
		ParseIntP[int](10, 0),
	)),
)

colTypeOp := ColTypeOp(colType, op)

data := lo.T2(1, []string{"1", "2", "3", "4"})

var result lo.Tuple2[int, []int]
result, err := Modify(T2BP[int, []string, []int](), colTypeOp, data)

fmt.Println(result, err)
Output:

{1 [1 2 3 4]} <nil>

func CombiColTypeErr

func CombiColTypeErr[ERR any, I, S, T, A, B any, OERR TPure](ct CollectionType[I, S, T, A, B, OERR]) CollectionType[I, S, T, A, B, ERR]

func MapColType

func MapColType[K comparable, S any]() CollectionType[K, map[K]S, map[K]S, S, S, Pure]

func MapColTypeP

func MapColTypeP[K comparable, S, T any]() CollectionType[K, map[K]S, map[K]T, S, T, Pure]

MapColTypeP returns a CollectionType wrapper for maps.

func SliceColType

func SliceColType[S any]() CollectionType[int, []S, []S, S, S, Pure]

SliceColType returns a CollectionType for slices

func SliceColTypeP

func SliceColTypeP[S, T any]() CollectionType[int, []S, []T, S, T, Pure]

SliceColTypeP returns a polymorphic CollectionType for slices.

Example
data := lo.T2(1, []string{
	"1",
	"2",
	"3",
	"4",
})

var result lo.Tuple2[int, []int]
var err error
result, err = Modify(
	Compose(
		T2BP[int, []string, []int](),
		TraverseColType(SliceColTypeP[string, int]()),
	),
	Compose(
		ParseInt[int](10, 0),
		Mul(2),
	),
	data,
)

fmt.Println(result, err)
Output:

{1 [2 4 6 8]} <nil>

func StringColType

func StringColType() CollectionType[int, string, string, rune, rune, Pure]
Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

//See: [FilteredString] for a more convenient string filter function.
var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		ColTypeOp(StringColType(), FilteredCol[int](In('a', 'e', 'i', 'o', 'u', ' '))),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	ColTypeOp(StringColType(), FilteredCol[int](In('a', 'e', 'i', 'o', 'u', ' '))),
	data,
)
fmt.Println(modifyRes)
Output:

oe iu oo i ae
{1 oe iu oo i ae}

func T2ColType

func T2ColType[A any]() CollectionType[int, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, Pure]

T2ColType returns a CollectionType wrapper for lo.Tuple2.

See: T2ColTypeP for a polymorphic version

func T2ColTypeP

func T2ColTypeP[A any, B any]() CollectionType[int, lo.Tuple2[A, A], lo.Tuple2[B, B], A, B, Pure]

T2ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple2.

See: T2ColType for a non polymorphic version

func T3ColType

func T3ColType[A any]() CollectionType[int, lo.Tuple3[A, A, A], lo.Tuple3[A, A, A], A, A, Pure]

T3ColType returns a CollectionType wrapper for lo.Tuple3.

See: T3ColTypeP for a polymorphic version

func T3ColTypeP

func T3ColTypeP[A any, B any]() CollectionType[int, lo.Tuple3[A, A, A], lo.Tuple3[B, B, B], A, B, Pure]

T3ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple3.

See: T3ColType for a non polymorphic version

func T4ColType

func T4ColType[A any]() CollectionType[int, lo.Tuple4[A, A, A, A], lo.Tuple4[A, A, A, A], A, A, Pure]

T4ColType returns a CollectionType wrapper for lo.Tuple4.

See: T4ColTypeP for a polymorphic version

func T4ColTypeP

func T4ColTypeP[A any, B any]() CollectionType[int, lo.Tuple4[A, A, A, A], lo.Tuple4[B, B, B, B], A, B, Pure]

T4ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple4.

See: T4ColType for a non polymorphic version

func T5ColType

func T5ColType[A any]() CollectionType[int, lo.Tuple5[A, A, A, A, A], lo.Tuple5[A, A, A, A, A], A, A, Pure]

T5ColType returns a CollectionType wrapper for lo.Tuple5.

See: T5ColTypeP for a polymorphic version

func T5ColTypeP

func T5ColTypeP[A any, B any]() CollectionType[int, lo.Tuple5[A, A, A, A, A], lo.Tuple5[B, B, B, B, B], A, B, Pure]

T5ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple5.

See: T5ColType for a non polymorphic version

func T6ColType

func T6ColType[A any]() CollectionType[int, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[A, A, A, A, A, A], A, A, Pure]

T6ColType returns a CollectionType wrapper for lo.Tuple6.

See: T6ColTypeP for a polymorphic version

func T6ColTypeP

func T6ColTypeP[A any, B any]() CollectionType[int, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[B, B, B, B, B, B], A, B, Pure]

T6ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple6.

See: T6ColType for a non polymorphic version

func T7ColType

func T7ColType[A any]() CollectionType[int, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[A, A, A, A, A, A, A], A, A, Pure]

T7ColType returns a CollectionType wrapper for lo.Tuple7.

See: T7ColTypeP for a polymorphic version

func T7ColTypeP

func T7ColTypeP[A any, B any]() CollectionType[int, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[B, B, B, B, B, B, B], A, B, Pure]

T7ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple7.

See: T7ColType for a non polymorphic version

func T8ColType

func T8ColType[A any]() CollectionType[int, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[A, A, A, A, A, A, A, A], A, A, Pure]

T8ColType returns a CollectionType wrapper for lo.Tuple8.

See: T8ColTypeP for a polymorphic version

func T8ColTypeP

func T8ColTypeP[A any, B any]() CollectionType[int, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[B, B, B, B, B, B, B, B], A, B, Pure]

T8ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple8.

See: T8ColType for a non polymorphic version

func T9ColType

func T9ColType[A any]() CollectionType[int, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[A, A, A, A, A, A, A, A, A], A, A, Pure]

T9ColType returns a CollectionType wrapper for lo.Tuple9.

See: T9ColTypeP for a polymorphic version

func T9ColTypeP

func T9ColTypeP[A any, B any]() CollectionType[int, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[B, B, B, B, B, B, B, B, B], A, B, Pure]

T9ColTypeP returns a polymorphic CollectionType wrapper for lo.Tuple9.

See: T9ColType for a non polymorphic version

type CompositionTree

type CompositionTree[L any, R any] struct {
	L L
	R R
}

Return type that indicates this optic is composed of other optics with potentially different return types. If any part of the composition tree is ReturnMany this optic would be considered ReturnMany any will fail compilation if passed to a ReturnOne action.

For some apis (e.g. CoalesceN) it may be necessary to condense the CompositionTree back to a ReturnOne or ReturnMany using the Ret1 or RetM functions. When implementing custom combinators it is considered best practice to condense the return type.

type Diff

type Diff[I, A any] struct {
	BeforeIndex I
	AfterIndex  I
	BeforePos   int
	AfterPos    int
	BeforeValue A
	Type        DiffType
	Distance    float64
}

func (Diff[I, A]) String

func (d Diff[I, A]) String() string

type DiffType

type DiffType int
const (
	DiffAdd DiffType = 1 << iota
	DiffRemove
	DiffModify
	DiffNone
)
const DiffNoFilter DiffType = 0

func (DiffType) String

func (d DiffType) String() string

type EditType

type EditType expr.EditType

type Err

type Err []Void

type ErrCast

type ErrCast struct {
	From reflect.Type //The expected typed to cast from.
	To   reflect.Type //The type that Of was being cast to.
}

func (*ErrCast) Error

func (e *ErrCast) Error() string

type ErrCastOf

type ErrCastOf struct {
	Of   reflect.Type //The type of the value that was being cast.
	From reflect.Type //The expected typed to cast from.
	To   reflect.Type //The type that Of was being cast to.
}

ErrCastOf means that a cast failed.

func (*ErrCastOf) Error

func (e *ErrCastOf) Error() string

type ExprHandler

type ExprHandler interface {
	TypeId() string

	Modify(ctx context.Context, o expr.OpticExpression, fmapExpr expr.OpticExpression, fmap func(index any, focus any, focusErr error) (any, error), source any) (any, bool, error)
	Set(ctx context.Context, o expr.OpticExpression, source any, val any) (any, error)
	Get(ctx context.Context, expr expr.OpticExpression, source any) (index any, value any, found bool, err error)
	ReverseGet(ctx context.Context, expr expr.OpticExpression, focus any) (any, error)
}

The ExprHandler interface allows optics to take control of the execution of the complete expression tree.

This can be used for example to translate optics to SQL statements.

type ExpressionDef

type ExpressionDef struct {
	// contains filtered or unexported fields
}

func ExprCustom

func ExprCustom(id string) ExpressionDef

func ExprDef

func ExprDef(
	expression func(t expr.OpticTypeExpr) expr.OpticExpression,
	subOptics ...asExprHandler,
) ExpressionDef

func ExprDefVarArgs

func ExprDefVarArgs[T asExprHandler](
	expression func(t expr.OpticTypeExpr) expr.OpticExpression,
	subOptics ...T,
) ExpressionDef

func ExprTODO

func ExprTODO(id string) ExpressionDef

type FilterMode

type FilterMode byte
const (
	FilterStop FilterMode = iota
	FilterContinue
	FilterYieldAll
)

type GetterFunc

type GetterFunc[I, S, A any] func(ctx context.Context, source S) (I, A, error)

View function for Operation type optics.

type Integer

type Integer interface {
	constraints.Integer
}

Type constraint for integer types

type IterFunc

type IterFunc[I, S, A any] func(ctx context.Context, source S) SeqIE[I, A]

View function for Iteration type optics.

type IxGetterFunc

type IxGetterFunc[I, S, A any] func(ctx context.Context, index I, source S) SeqIE[I, A]

View by index function for Traversal type optics

type IxMapper

type IxMapper[LEFT, RIGHT, MAPPED any, RET TReturnOne, RW any, DIR any, ERR TPure] Optic[MAPPED, lo.Tuple2[mo.Option[LEFT], mo.Option[RIGHT]], lo.Tuple2[mo.Option[LEFT], mo.Option[RIGHT]], MAPPED, MAPPED, RET, RW, DIR, ERR]

func IxMap

func IxMap[LEFT, RIGHT, MAPPED any](ixmap func(LEFT, RIGHT) MAPPED) IxMapper[LEFT, RIGHT, MAPPED, ReturnOne, ReadOnly, UniDir, Pure]

IxMap returns a simple IxMapper where the left and right indexes cannot be recovered from the mapped value

Note: For a more efficient composition when used as an Traversal optic then IxMapIso should be used.

See: ComposeI for an example usage

Example
//This example demonstrates the custom index mapping
//for an example on composition in general check the Compose function
data := [][]int{
	{1, 2, 3},
	{4, 5},
	{6, 7, 8},
}

//Combine the 2 indices into an array rather than the
//[lo.Tuple2] returned by ComposeBoth
//Even though The mapping is technically lossless IxMap does not support
//recovering the original indexes and [Traversal] operations will be inefficient
//See: [IxMapF] for an efficient version.
ixMap := IxMap(
	//ixmap
	func(left int, right int) [2]int {
		return [2]int{left, right}
	},
)

//The composed optic focuses on the individual ints in the nested slices.
composedOptic := ComposeI(ixMap, TraverseSlice[[]int](), TraverseSlice[int]())

//Note that the index in the result is [2]int the result of our ixMap function
var listOfResult []ValueI[[2]int, int] = MustGet(SliceOf(WithIndex(composedOptic), 8), data)
fmt.Println(listOfResult) //[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]

//Over applies the custom function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the int value is multiplied by 100 only if both slice indices are even.
var overResult [][]int = MustModifyI(composedOptic, OpI(func(index [2]int, focus int) int {
	if index[0]%2 == 0 && index[1]%2 == 0 {
		return focus * 100
	}
	return focus
}), data)
fmt.Println(overResult) //[[100 2 300] [4 5] [600 7 800]]

//Index uses the composed index to lookup the element at
//data[1][1]
//Note: the Index lookup will be inefficient as we have not used IxMapF's unmap support.
indexResult, found := MustGetFirst(Index(composedOptic, [2]int{1, 1}), data)
fmt.Println(indexResult, found) //5 true
Output:

[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]
[[100 2 300] [4 5] [600 7 800]]
5 true

func IxMapBoth

func IxMapBoth[I, J any](
	ixmatchI func(I, I) bool,
	ixmatchJ func(J, J) bool,
) IxMapper[I, J, lo.Tuple2[I, J], ReturnOne, ReadWrite, BiDir, Pure]
Example
data := map[string]lo.Tuple2[int, string]{
	"a": lo.T2(10, "alpha"),
	"b": lo.T2(11, "beta"),
	"c": lo.T2(12, "gamma"),
}

optic := ComposeI(
	IxMapBoth[string, int](IxMatchComparable[string](), IxMatchComparable[int]()),
	TraverseMap[string, lo.Tuple2[int, string]](),
	T2B[int, string](),
)

res := MustGet(SeqIOf(optic), data)
fmt.Println(res)
Output:

Seq[{a 1}:alpha {b 1}:beta {c 1}:gamma]

func IxMapIso

func IxMapIso[LEFT, RIGHT, MAPPED any](
	ixmap func(left LEFT, right RIGHT) MAPPED,
	ixmatch func(a, b MAPPED) bool,
	unmap func(mapped MAPPED) (LEFT, bool, RIGHT, bool),
	exprDef ExpressionDef,
) IxMapper[LEFT, RIGHT, MAPPED, ReturnOne, ReadWrite, BiDir, Pure]

IxMapIso returns a IxMapper where the left and right may be recovered from the mapped value This enables more efficient operation when the composed optic is used as an Traversal

See: IxMap for a simpler inefficient version.

Example
//This example demonstrates the custom index mapping
//for an example on composition in general check the Compose function
data := [][]int{
	{1, 2, 3},
	{4, 5},
	{6, 7, 8},
}

//Combine the 2 indices into an array rather than the
//[lo.Tuple2] returned by ComposeBoth
//The mapping is lossless so we can recover the left and right components
//This enables indexed operations to be performed in an efficient way.
ixMap := IxMapIso[int, int, [2]int](
	//ixmap
	func(left int, right int) [2]int {
		return [2]int{left, right}
	},
	//ixmatch
	func(i1, i2 [2]int) bool {
		return i1[0] == i2[0] && i1[1] == i2[1]
	},
	//unmap
	func(mapped [2]int) (int, bool, int, bool) {
		return mapped[0], true, mapped[1], true
	},
	ExprCustom("ExampleIxMapF"),
)

//The composed optic focuses on the individual ints in the nested slices.
composedOptic := ComposeI(ixMap, TraverseSlice[[]int](), TraverseSlice[int]())

//Note that the index in the result is [2]int the result of our ixMap function
var listOfResult []ValueI[[2]int, int] = MustGet(SliceOf(WithIndex(composedOptic), 8), data)
fmt.Println(listOfResult) //[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]

//Over applies the custom function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the int value is multiplied by 100 only if both slice indices are even.
var overResult [][]int = MustModifyI(composedOptic, OpI(func(index [2]int, focus int) int {
	if index[0]%2 == 0 && index[1]%2 == 0 {
		return focus * 100
	}
	return focus
}), data)
fmt.Println(overResult) //[[100 2 300] [4 5] [600 7 800]]

//Index uses the composed index to lookup the element at
//data[1][1]
//Note: the given unmap function will be used to perform an efficient lookup.
indexResult, found := MustGetFirst(Index(composedOptic, [2]int{1, 1}), data)
fmt.Println(indexResult, found) //5 true
Output:

[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]
[[100 2 300] [4 5] [600 7 800]]
5 true

func IxMapLeft

func IxMapLeft[I, J any](ixmatch func(I, I) bool) IxMapper[I, J, I, ReturnOne, ReadWrite, BiDir, Pure]
Example
data := map[string]lo.Tuple2[int, string]{
	"a": lo.T2(10, "alpha"),
	"b": lo.T2(11, "beta"),
	"c": lo.T2(12, "gamma"),
}

optic := ComposeI(
	IxMapLeft[string, int](IxMatchComparable[string]()),
	TraverseMap[string, lo.Tuple2[int, string]](),
	T2B[int, string](),
)

res := MustGet(SeqIOf(optic), data)
fmt.Println(res)
Output:

Seq[a:alpha b:beta c:gamma]

func IxMapRight

func IxMapRight[I, J any](ixmatch func(J, J) bool) IxMapper[I, J, J, ReturnOne, ReadWrite, BiDir, Pure]
Example
data := map[string]lo.Tuple2[int, string]{
	"a": lo.T2(10, "alpha"),
	"b": lo.T2(11, "beta"),
	"c": lo.T2(12, "gamma"),
}

optic := ComposeI(
	IxMapRight[string, int](IxMatchComparable[int]()),
	TraverseMap[string, lo.Tuple2[int, string]](),
	T2B[int, string](),
)

res := MustGet(SeqIOf(optic), data)
fmt.Println(res)
Output:

Seq[1:alpha 1:beta 1:gamma]

type IxMatchFunc

type IxMatchFunc[I any] func(indexA I, indexB I) bool

type LengthGetterFunc

type LengthGetterFunc[S any] func(ctx context.Context, source S) (int, error)

Length getter function for Iteration type optics

type MakeLensCmpOps

type MakeLensCmpOps[I, S, T any, A comparable, RET, RW, DIR, ERR any] struct {
	Optic[I, S, T, A, A, RET, RW, DIR, ERR]
}

MakeLensCmpOps is used internally by the makelens tool.

func NewMakeLensCmpOps

func NewMakeLensCmpOps[I, S, T any, A comparable, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR]) MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]

NewMakeLensCmpOps is used internally by the makelens tool.

func (MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Contains

func (o MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Contains(val A) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func (MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Eq

func (o MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Eq(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) In

func (o MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) In(val ...A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Ne

func (o MakeLensCmpOps[I, S, T, A, RET, RW, DIR, ERR]) Ne(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

type MakeLensMap

type MakeLensMap[I comparable, S, T, A, RET, RW, DIR, ERR any] struct {
	Optic[Void, S, T, Collection[I, A, Pure], Collection[I, A, Pure], RET, RW, UniDir, ERR]
	// contains filtered or unexported fields
}

MakeLensMap is used internally by the makelens tool.

func NewMakeLensMap

func NewMakeLensMap[I comparable, S, T, A, RET any, RW any, DIR any, ERR any](o Optic[Void, S, T, map[I]A, map[I]A, RET, RW, DIR, ERR]) MakeLensMap[I, S, T, A, RET, RW, DIR, ERR]

MakeLensMap is used internally by the makelens tool.

func (MakeLensMap[I, S, T, A, RET, RW, DIR, ERR]) Key

func (s MakeLensMap[I, S, T, A, RET, RW, DIR, ERR]) Key(index I) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

func (MakeLensMap[I, S, T, A, RET, RW, DIR, ERR]) Traverse

func (s MakeLensMap[I, S, T, A, RET, RW, DIR, ERR]) Traverse() Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

type MakeLensOrdOps

type MakeLensOrdOps[I, S, T any, A cmp.Ordered, RET, RW, DIR, ERR any] struct {
	Optic[I, S, T, A, A, RET, RW, DIR, ERR]
}

MakeLensOrdOps is used internally by the makelens tool.

func NewMakeLensOrdOps

func NewMakeLensOrdOps[I, S, T any, A cmp.Ordered, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR]) MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]

NewMakeLensOrdOps is used internally by the makelens tool.

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Contains

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Contains(val A) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Eq

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Eq(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Gt

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Gt(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Gte

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Gte(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) In

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) In(val ...A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Lt

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Lt(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Lte

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Lte(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Ne

func (o MakeLensOrdOps[I, S, T, A, RET, RW, DIR, ERR]) Ne(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

type MakeLensRealOps

type MakeLensRealOps[I, S, T any, A Real, RET, RW, DIR, ERR any] struct {
	Optic[I, S, T, A, A, RET, RW, DIR, ERR]
}

MakeLensRealOps is used internally by the makelens tool.

func NewMakeLensRealOps

func NewMakeLensRealOps[I, S, T any, A Real, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR]) MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]

NewMakeLensRealOps is used internally by the makelens tool.

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Add

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Add(val A) Optic[I, S, T, A, A, RET, RW, DIR, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Contains

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Contains(val A) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Div

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Div(val A) Optic[I, S, T, A, A, RET, RW, DIR, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Eq

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Eq(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Gt

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Gt(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Gte

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Gte(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) In

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) In(val ...A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Lt

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Lt(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Lte

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Lte(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Max

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Max(val A) Optic[I, S, T, A, A, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Min

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Min(val A) Optic[I, S, T, A, A, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Mul

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Mul(val A) Optic[I, S, T, A, A, RET, RW, DIR, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Ne

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Ne(val A) Optic[I, S, T, bool, bool, RET, ReadOnly, UniDir, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Negate

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Negate() Optic[I, S, T, A, A, RET, RW, DIR, ERR]

func (MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Sub

func (o MakeLensRealOps[I, S, T, A, RET, RW, DIR, ERR]) Sub(val A) Optic[I, S, T, A, A, RET, RW, DIR, ERR]

type MakeLensSlice

type MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR any] struct {
	Optic[I, S, T, Collection[int, A, Pure], Collection[int, A, Pure], RET, RW, UniDir, ERR]
	// contains filtered or unexported fields
}

MakeLensSlice is used internally by the makelens tool.

func NewMakeLensSlice

func NewMakeLensSlice[I, S, T, A, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, []A, []A, RET, RW, DIR, ERR]) MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR]

NewMakeLensSlice is used internally by the makelens tool.

func (MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR]) Nth

func (s MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR]) Nth(index int) Optic[int, S, T, A, A, ReturnMany, RW, UniDir, ERR]

func (MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR]) Traverse

func (s MakeLensSlice[I, S, T, A, RET, RW, DIR, ERR]) Traverse() Optic[int, S, T, A, A, ReturnMany, RW, UniDir, ERR]

type MatchIndex

type MatchIndex struct {
	Offsets  []int
	Captures []string
}

type Metrics

type Metrics struct {
	Focused   int //Indicates how many elements were focused.
	Access    int //Indicates how many times the source was accessed.
	LengthGet int //Indicates how many LengthGets were performed.
	IxGet     int //Indicates how many index lookups were performed.

	Custom map[string]int //Custom metrics
}

Metrics contains information about the execution of an Optic.

See:

func (Metrics) String

func (m Metrics) String() string

type ModifyFunc

type ModifyFunc[I, S, T, A, B any] func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error)

Modification function for Traversal type optics.

type OpGetFunc

type OpGetFunc[S, A any] func(ctx context.Context, source S) (A, error)

type Operation

type Operation[S, A any, RET TReturnOne, ERR any] interface {
	AsOpGet() OpGetFunc[S, A]
	ReturnType() RET
	ErrType() ERR
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)
	AsExpr() expr.OpticExpression
}

The Operation interface is a simplified read only version of the Optic interface used for operators and predicates. Provides access to the low level optic implementation functions. These functions are not intended for general user use but are provided to enable efficient combinators and actions to be implemented in external packages.

type OperationI

type OperationI[I, S, A any, RET TReturnOne, ERR any] Operation[ValueI[I, S], A, RET, ERR]

The OperationI interface is a simplified read only version of the Optic interface used for operators and predicates. Provides access to the low level optic implementation functions. These functions are not intended for general user use but are provided to enable efficient combinators and actions to be implemented in external packages.

type Optic

type Optic[I, S, T, A, B, RET, RW, DIR, ERR any] interface {
	// Provides this optics [Traversal] style modification function.
	// This methods behavior is only defined for [ReadWrite] optics.
	AsModify() ModifyFunc[I, S, T, A, B]

	// Provides this optics [Iteration] style view function.
	// This methods behavior is defined for all optic types
	AsIter() IterFunc[I, S, A]

	// Provides this optics [Operation] style view function.
	// This methods behavior is only defined for [ReturnOne] optics.
	AsGetter() GetterFunc[I, S, A]

	// Provides this optics [Lens] style modification function.
	// This methods behavior is only defined for [ReadWrite] optics.
	AsSetter() SetterFunc[S, T, B]

	// Provides this optics [Traversal] style view by index function.
	// This methods behavior is only defined for all optics.
	AsIxGetter() IxGetterFunc[I, S, A]

	AsIxMatch() IxMatchFunc[I]

	// Provides this optics [Iso] or [Prism] style modification function.
	// This methods behavior is only defined for all [BiDir]
	AsReverseGetter() ReverseGetterFunc[T, B]

	// Provides this optics [Iteration] style length getter function.
	// This methods behavior is defined for all optic types
	AsLengthGetter() LengthGetterFunc[S]

	AsOpGet() OpGetFunc[S, A]

	// Provides this optics expression tree representation.
	AsExpr() expr.OpticExpression

	//Provides the custom expression handler. Used by non go backends to execute expressions
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)

	// Provides this optics internal type. This indicates which methods have efficient implementations.
	OpticType() expr.OpticType

	// Indicates whether this optic returns exactly 1 result [ReturnOne] or 0 or more [ReturnMany]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [ReturnMany]
	// optic is passed to an action that requires a [ReturnOne] result. e.g. [View].
	ReturnType() RET

	// Indicates whether this optic supports modification [ReadWrite] or can only be viewed [ReadOnly]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [ReadOnly]
	// optic is passed to a modification action e.g. [Over].
	ReadWriteType() RW

	// Indicates whether this optic supports ReverseGet [BiDir] or is unidirectional [UniDir]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [UniDir]
	// optic is passed to an action requiring a reverseget e.g. [ReView].
	DirType() DIR

	ErrType() ERR
}

Optic interface implemented by all optic types. Provides access to the low level optic implementation functions. These functions are not intended for general user use but are provided to enable efficient combinators and actions to be implemented in external packages.

func Abs

func Abs[A Real]() Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Abs returns a Operation that focuses on the absolute value.

Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 1),
	lo.T2("b", -2),
	lo.T2("c", 3),
	lo.T2("d", -4),
	lo.T2("e", 5),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Abs each focused int.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Abs[int](), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition negates then Adds 2
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Abs[int](), Add(2)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
var preComposedResult []int = MustGet(SliceOf(Compose(optic, Abs[int]()), 5), data)
fmt.Println(preComposedResult)
Output:

[{a 1} {b 2} {c 3} {d 4} {e 5}]
[{a 3} {b 4} {c 5} {d 6} {e 7}]
[1 2 3 4 5]

func Add

func Add[A Arithmetic](right A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Add returns a Iso that performs an addition by a constant value.

See:

  • AddOp for a version that is applied to the focus of 2 [Operation]s.
  • Sum for a Reducer variant.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 1),
	lo.T2("b", 2),
	lo.T2("c", 3),
	lo.T2("d", 4),
	lo.T2("e", 5),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Add 10 to each focused int.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Add(10), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition Adds 10 then multiplies by 2
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Add(10), Mul(2)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Mul operation in a add 10 context
//But when the result is built the value is subtracted by 10 again to return it to the original context
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Add(10)), Mul(2), data)
fmt.Println(preComposedResult)
Output:

[{a 11} {b 12} {c 13} {d 14} {e 15}]
[{a 22} {b 24} {c 26} {d 28} {e 30}]
[{a 12} {b 14} {c 16} {d 18} {e 20}]

func AddOp

func AddOp[S any, A Arithmetic, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

AddOp returns an Operation expression that adds the focuses of 2 [Operation]s.

See:

  • Add for the constant version.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 6),
	lo.T2(2, 7),
	lo.T2(3, 8),
	lo.T2(4, 9),
	lo.T2(5, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Add function to the focuses of both optics
adder := AddOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(adder, lo.T2(2, 10))
fmt.Println(singleValueResult) // 12

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), adder, data)
fmt.Println(overResult) // [6 14 24 36 50]
Output:

12
[7 9 11 13 15]

func AddT2

func AddT2[A Arithmetic]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

AddT2 returns an BinaryOp that adds 2 values.

See:

  • Add for a unary version.
  • AddOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []int{5, 2, 10, 3}

//returns a reducer that sums all the numbers in a slice
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(0, AddT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

20 true

func All

func All[I, S, T, A, B, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], pred Predicate[A, PERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, PERR]]

All returns a Predicate that is satisfied if all focuses satisfy the passed predicate

Note: If the optic focuses no elements then All returns true.

See:

  • AllI for an index aware version.
  • Any for a version that is satisfied if any focus satisfies the predicate.
Example
data := []int{10, 20, 30, 40}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

var result bool
var err error
result, err = Get(All(optic, Gt(5)), data)
fmt.Println(result, err)
Output:

true <nil>

func AllI

func AllI[I, S, T, A, B, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], pred PredicateI[I, A, PERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, PERR]]

AllI returns an PredicateI that is satisfied if all focused satisfy the given predicate

Note: If the optic focuses no elements then AllI returns true.

See:

  • All for a non index aware version.
  • AnyI for a version that requires that any focuses satisfies the predicate.
Example
data := []int{1, 20, 3, 40}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

var result bool
var err error
result, err = Get(AllI(optic, OpI(func(index int, focus int) bool {
	//even index or value is > 5
	return index%2 == 0 || focus > 5
})), data)
fmt.Println(result, err)
Output:

true <nil>

func And

And returns an Operation that performs a logical and with a constant value.

See:

  • [IAnd] for an OperationI version
  • AndOp for a version that is applied to the focus of 2 getters.

func AndOp

func AndOp[S, LERR, RERR any](left Predicate[S, LERR], right Predicate[S, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

AndOp returns an Operation that logically ands the value of the left getter with the right getters value

See:

  • And for the constant version
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
	lo.T2(3, 1),
}

//returns a predicate that matches if A>B in the tuple
predicateGt := GtOp(T2A[int, int](), T2B[int, int]())
//returns a predicate that matches if A==2 in the tuple
predicateEq2 := Compose(T2A[int, int](), Eq(2))

//These 2 predicates are compatible as they have an int source type. They can be combined into an And predicate
predicateAnd := AndOp(predicateGt, predicateEq2)

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicateAnd)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

//We can focus on this composite filter predicate and modify the focused element by adding 10
var overResult []lo.Tuple2[int, int] = MustModify(Compose(filterOptic, T2B[int, int]()), Add(10), data)
fmt.Println(overResult)
Output:

[{2 1}]
[{1 1} {1 2} {2 11} {2 2} {3 1}]

func AndT2

AndT2 returns an BinaryOp that performs a logical and

See:

  • And for a unary version.
  • AndOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []bool{true, false, true, true, true}

//The And function can be converted to a Reducer to detect if all focused values are true in a traversal where the empty traversal is considered to be all true values.
result, ok := MustGetFirst(Reduce(TraverseSlice[bool](), AsReducer(true, AndT2())), data)
fmt.Println(result, ok)
Output:

false true

func Any

func Any[I, S, T, A, B, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], pred Predicate[A, PERR]) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, PERR]]

Any returns a Predicate that is satisfied if any focus satisfies the passed predicate.

Note: If the optic focuses no elements then Any returns false.

See

  • AnyI for an index aware version.
  • All for a version that is satisified if all focuses satisfy the predicate.
Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result bool
var err error
result, err = Get(Any(optic, Eq("3")), data)
fmt.Println(result, err)
Output:

true <nil>

func AnyI

func AnyI[I, S, T, A, B, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], pred PredicateI[I, A, PERR]) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, PERR]]

AnyI returns an Predicate that is satisfied if any focus satisfies the given predicate

Note: If the optic focuses no elements then Any returns false.

See:

  • Any for a non index aware version.
  • AllI for a version that requires that all focuses satisfy the predicate.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result bool
var err error
result, err = Get(AnyI(optic, EqI[string](2)), data)
fmt.Println(result, err)
Output:

true <nil>

func Append

func Append[A any](toAppend ...A) Optic[Void, Collection[int, A, Pure], Collection[int, A, Pure], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadOnly, UniDir, Pure]

Append returns a Lens that appends additional integer indexed elements to the end of the source Collection.

See:

Example
data := []string{
	"alpha",
	"beta",
}

var result []string = MustModify(
	SliceToCol[string](),
	Append("gamma", "delta"),
	data,
)

fmt.Println(result)
Output:

[alpha beta gamma delta]

func AppendCol

func AppendCol[I, A, ERR any](toAppend Collection[I, A, ERR]) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadOnly, UniDir, ERR]

AppendCol returns a Lens that appends additional elements to the end of the source Collection.

See:

  • [AppendColP] for a polymorphic version
  • PrependCol for a prepend version
Example
data := []string{
	"alpha",
	"beta",
}

var result []string = MustModify(
	SliceToCol[string](),
	AppendCol(
		ValCol("gamma", "delta"),
	),
	data,
)

fmt.Println(result)
Output:

[alpha beta gamma delta]

func AppendColT2

func AppendColT2[I, A, ERR any]() Optic[Void, lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadOnly, UniDir, ERR]

func AppendColTypeT2

func AppendColTypeT2[I, S, A any, ERR any](s CollectionType[I, S, S, A, A, ERR]) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], S, S, ReturnOne, ReadOnly, UniDir, ERR]

func AppendMap

func AppendMap[K comparable, S any, ERR any](toAppend Collection[K, S, ERR]) Optic[Void, map[K]S, map[K]S, map[K]S, map[K]S, ReturnOne, ReadOnly, UniDir, ERR]

AppendMap applies the Append operation to a Map

Example
data := lo.T2(
	1,
	map[int]string{
		1: "alpha",
		2: "beta",
	},
)

var getRes map[int]string = MustGet(
	Compose(
		T2B[int, map[int]string](),
		AppendMap[int](MapCol(map[int]string{3: "gamma", 4: "delta"})),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, map[int]string] = MustModify(
	T2B[int, map[int]string](),
	AppendMap[int](MapCol(map[int]string{3: "gamma", 4: "delta"})),
	data,
)
fmt.Println(modifyRes)
Output:

map[1:alpha 2:beta 3:gamma 4:delta]
{1 map[1:alpha 2:beta 3:gamma 4:delta]}

func AppendMapT2

func AppendMapT2[K comparable, S any, I, ERR any]() Optic[Void, lo.Tuple2[map[K]S, map[K]S], lo.Tuple2[map[K]S, map[K]S], map[K]S, map[K]S, ReturnOne, ReadOnly, UniDir, ERR]

AppendMapT2 applies the AppendColT2 operation to a Map

func AppendSlice

func AppendSlice[A any, ERR any](toAppend Collection[int, A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadOnly, UniDir, ERR]

AppendSlice applies the Append operation to a Slice

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		AppendSlice(ValCol("gamma", "delta")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	AppendSlice(ValCol("gamma", "delta")),
	data,
)
fmt.Println(modifyRes)
Output:

[alpha beta gamma delta]
{1 [alpha beta gamma delta]}

func AppendSliceT2

func AppendSliceT2[A any, I, ERR any]() Optic[Void, lo.Tuple2[[]A, []A], lo.Tuple2[[]A, []A], []A, []A, ReturnOne, ReadOnly, UniDir, ERR]

AppendSliceT2 applies the AppendColT2 operation to a Slice

func AppendString

func AppendString[ERR any](toAppend Collection[int, rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadOnly, UniDir, ERR]

AppendString applies the Append operation to a String

Example
data := lo.T2(1, "Lorem ipsum dolor sit")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		AppendString(StringCol(" amet")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	AppendString(StringCol(" amet")),
	data,
)
fmt.Println(modifyRes)
Output:

Lorem ipsum dolor sit amet
{1 Lorem ipsum dolor sit amet}

func AppendStringT2

func AppendStringT2[I, ERR any]() Optic[Void, lo.Tuple2[string, string], lo.Tuple2[string, string], string, string, ReturnOne, ReadOnly, UniDir, ERR]

AppendStringT2 applies the AppendColT2 operation to a String

func AsIxGet

func AsIxGet[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, ValueI[I, S], ValueI[I, S], mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, ERR]

AsIxGet is a combinator that converts a Traversal to an OperationI that operates on the combined index and source.

See:

  • OpToOpI for a combinator that converts an Operator and ignores the index
  • OpOnIx for a version that operates on on the index only.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := AsIxGet(TraverseMap[int, string]())

var result mo.Option[string] = MustGet(optic, ValI(1, data))
fmt.Println(result)

result = MustGet(optic, ValI(10, data))
fmt.Println(result)
Output:

{true alpha}
{false }

func AsIxMatchT2

func AsIxMatchT2[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, lo.Tuple2[I, I], lo.Tuple2[I, I], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

func AsModify

func AsModify[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, ORET TReturnOne, ERR, OERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap Operation[A, B, ORET, OERR]) Optic[Void, S, S, T, T, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, OERR]]

AsModify is a combinator that returns an Operation that applies the op as a modification to the given Optic

See:

Example
data := "1"

var result int
result, err := Get(
	AsModify(
		ParseIntP[int](10, 32),
		Add(1),
	),
	data,
)

fmt.Println(result, err)
Output:

2 <nil>

func AsModifyI

func AsModifyI[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, ORET TReturnOne, ERR, OERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], fmap OperationI[I, A, B, ORET, OERR]) Optic[Void, S, S, T, T, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, OERR]]

AsModifyI is an index aware combinator that returns an Operation that applies the op as a modification to the given Optic

See:

  • AsModify for a non index aware version.
  • ModifyI for an action equivalent.

func AsReverseGet

func AsReverseGet[I, S, T, A, B any, RET TReturnOne, RW TReadWrite, DIR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, B, A, T, S, ReturnOne, ReadWrite, BiDir, ERR]

The AsReverseGet combinator reverses the direction of an Iso.

See:

  • Embed for a version that works with [Prism]s
Example
celsiusToFahrenheit := Compose(Mul(1.8), Add(32.0))

var fahrenheit float64 = MustGet(celsiusToFahrenheit, 32)
fmt.Println(fahrenheit)

fahrenheitToCelsius := AsReverseGet(celsiusToFahrenheit)

var celsius float64 = MustGet(fahrenheitToCelsius, 90)
fmt.Println(celsius)

//Note: this result is in fahrenheit but the 10 is added in celsius
var add10CelsiusResult float64 = MustModify(fahrenheitToCelsius, Add(10.0), 90)
fmt.Println(add10CelsiusResult)
Output:

89.6
32.22222222222222
108

func AsSet

func AsSet[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, ORET TReturnOne, ERR, OERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], val Operation[S, B, ORET, OERR]) Optic[Void, S, S, T, T, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, OERR]]

AsSet is a combinator that returns an Operation that focuses the result of setting the given val using the given optic

See:

  • Set for an action equivalent.
Example
data := "1"

var result int
result, err := Get(
	AsSet(
		ParseIntP[int](10, 32),
		Const[string](2),
	),
	data,
)

fmt.Println(result, err)
Output:

2 <nil>

func AtMap

func AtMap[K comparable, V any](index K) Optic[K, map[K]V, map[K]V, mo.Option[V], mo.Option[V], ReturnOne, ReadWrite, UniDir, Pure]

AtMap returns a Lens that focuses the index slot in a map. When viewing the none option means no element was present in the map with the given index. When modifying the none option will remove the element from the map.

See:

  • AtMapT2 for a version that can use a dynamic index.
  • Element for an optic that focuses by index position.
  • [IndexMap] for a version without the optional focus
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := AtMap[int, string](5)

var viewResult mo.Option[string] = MustGet(optic, data)
fmt.Println(viewResult)

var modifyResult map[int]string = MustSet(optic, mo.Some("epsilon"), data)
fmt.Println(modifyResult)

var deleteResult map[int]string = MustSet(AtMap[int, string](2), mo.None[string](), data)
fmt.Println(deleteResult)

//At can be composed with Non to provide a default value.

defaultValueOptic := Compose(AtMap[int, string](6), Non("default", EqT2[string]()))

var defaultViewResult string = MustGet(defaultValueOptic, data)
fmt.Println(defaultViewResult)
Output:

{false }
map[1:alpha 2:beta 3:gamma 4:delta 5:epsilon]
map[1:alpha 3:gamma 4:delta]
default

func AtMapT2

func AtMapT2[K comparable, V any]() Optic[K, lo.Tuple2[map[K]V, K], lo.Tuple2[map[K]V, K], mo.Option[V], mo.Option[V], ReturnOne, ReadWrite, UniDir, Pure]

AtMapT2 returns a Lens that focuses the element at tuple.B in a map tuple.A. When viewing the none option means no element was present in the map with the given index. When modifying the none option will remove the element from the map.

See:

  • AtMap for a version that uses a fixed index..
  • Element for an optic that focuses by index position.
  • [IndexMap] for a version without the optional focus

func AtSlice

func AtSlice[V, ERR any](index int, equals Predicate[lo.Tuple2[V, V], ERR]) Optic[int, []V, []V, mo.Option[V], mo.Option[V], ReturnOne, ReadWrite, UniDir, ERR]

AtSlice returns a Lens that focuses the index slot in a slice. When viewing the none option means either the slice was too small or the value was the uninitialized value. When modifying the slice will expand if necessary and be filled with uninitialized value as needed.

See:

  • AtSliceT2 for a version that can use a dynamic index.
  • Element for an optic that focuses by index position.
  • [IndexSlice] for a version without the optional focus
Example
data := []int{1, 2, 3}

optic := AtSlice[int](1, EqT2[int]())

var getResult mo.Option[int] = MustGet(
	optic,
	data,
)
fmt.Println(getResult)

var setResult []int = MustSet(
	optic,
	mo.Some(10),
	data,
)
fmt.Println(setResult)

optic = AtSlice[int](10, EqT2[int]())

getResult = MustGet(
	optic,
	data,
)
fmt.Println(getResult)

setResult = MustSet(
	optic,
	mo.Some(10),
	data,
)
fmt.Println(setResult)
Output:

{true 2}
[1 10 3]
{false 0}
[1 2 3 0 0 0 0 0 0 0 10]

func AtSliceT2

func AtSliceT2[V, ERR any](equals Predicate[lo.Tuple2[V, V], ERR]) Optic[int, lo.Tuple2[[]V, int], lo.Tuple2[[]V, int], mo.Option[V], mo.Option[V], ReturnOne, ReadWrite, UniDir, ERR]

AtSliceT2 returns a Lens that focuses the tuple.B index slot in a slice tuple.A. When viewing the none option means either the slice was too small or the value was the uninitialized value. When modifying the slice will expand if necessary and be filled with uninitialized value as needed.

See:

  • AtSlice for a version that uses a fixed index..
  • Element for an optic that focuses by index position.
  • [IndexSlice] for a version without the optional focus

func Bd

func Bd[I, S, T, A, B any, RET any, RW TReadWrite, DIR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, BiDir, ERR]

The Bd re-constrain converts an Optic with a complex but BiDir direction type to BiDir

DIR TBiDir --> BiDir

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Pure],
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrained Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	Pure,
] = Ret1(Rw(Bd(EPure(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Iso

func BesideEither

func BesideEither[IL, IR, SL, TL, SR, TR, A any, B any, RETL, RETR any, RWL, RWR any, DIRL, DIRR any, LERR, RERR any](left Optic[IL, SL, TL, A, B, RETL, RWL, DIRL, LERR], right Optic[IR, SR, TR, A, B, RETR, RWR, DIRR, RERR]) Optic[mo.Either[IL, IR], mo.Either[SL, SR], mo.Either[TL, TR], A, B, CompositionTree[RETL, RETR], CompositionTree[RWL, RWR], UniDir, CompositionTree[LERR, RERR]]

BesideEither returns a Traversal that focuses the elements in either the left or right optics depending whether the source is left or right.

Example
data := []mo.Either[lo.Tuple2[string, int], lo.Tuple2[int, string]]{
	mo.Left[lo.Tuple2[string, int], lo.Tuple2[int, string]](lo.T2("alpha", 1)),
	mo.Right[lo.Tuple2[string, int], lo.Tuple2[int, string]](lo.T2(2, "beta")),
	mo.Left[lo.Tuple2[string, int], lo.Tuple2[int, string]](lo.T2("gamma", 3)),
	mo.Right[lo.Tuple2[string, int], lo.Tuple2[int, string]](lo.T2(4, "delta")),
}

leftOptic := T2A[string, int]()
rightOptic := T2B[int, string]()

optic := Compose(
	TraverseSlice[mo.Either[lo.Tuple2[string, int], lo.Tuple2[int, string]]](),
	BesideEither(leftOptic, rightOptic),
)

var viewResult []string = MustGet(SliceOf(optic, len(data)), data)
fmt.Println(viewResult)

overResult := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[alpha beta gamma delta]
[{true {ALPHA 1} {0 }} {false { 0} {2 BETA}} {true {GAMMA 3} {0 }} {false { 0} {4 DELTA}}]

func BesideT2

func BesideT2[IL, IR, SL, SR, TR, TL, A, B, RETL, RETR any, RWL, RWR TReadWrite, DIRL, DIRR any, LERR, RERR any](left Optic[IL, SL, TL, A, B, RETL, RWL, DIRL, LERR], right Optic[IR, SR, TR, A, B, RETR, RWR, DIRR, RERR]) Optic[mo.Either[IL, IR], lo.Tuple2[SL, SR], lo.Tuple2[TL, TR], A, B, ReturnMany, CompositionTree[RWL, RWR], UniDir, CompositionTree[LERR, RERR]]

BesideT2 returns a Traversal that focuses all elements in both provided optics by returning an optic with a combined lo.Tuple2 source and result types.

Example
data1 := []int{10, 20, 30}
data2 := map[string]int{
	"alpha": 40,
	"beta":  50,
	"gamma": 60,
	"delta": 70,
}
data := lo.T2(data1, data2)

optic1 := TraverseSlice[int]()
optic2 := TraverseMap[string, int]()

beside := BesideT2(optic1, optic2)

var listRes []int = MustGet(SliceOf(beside, 4), data)
fmt.Println(listRes)

var overResult lo.Tuple2[[]int, map[string]int] = MustModify(beside, Mul(2), data)
fmt.Println(overResult)
Output:

[10 20 30 40 50 70 60]
{[20 40 60] map[alpha:80 beta:100 delta:140 gamma:120]}

func BinaryOp

func BinaryOp[L, R, V any](op func(left L, right R) V, exprOp string) Optic[Void, lo.Tuple2[L, R], lo.Tuple2[L, R], V, V, ReturnOne, ReadOnly, UniDir, Pure]

BinaryOp returns an Operation version of the given operator function. This constructor is a convenience wrapper for Operator with a simpler expression parameter.

The following additional constructors are available:

Example
customGreaterThan := BinaryOp(func(left, right int) bool { return left > right }, ">")

data := []int{1, 2, 3, 4, 5}

var filtered []int = MustGet(SliceOf(Filtered(TraverseSlice[int](), OpT2Bind(customGreaterThan, 3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), OpT2Bind(customGreaterThan, 3), data)
fmt.Println(overResult)
Output:

[4 5]
[false false false true true]

func BinaryOpE

func BinaryOpE[L, R, V any](op func(ctx context.Context, left L, right R) (V, error), exprOp string) Optic[Void, lo.Tuple2[L, R], lo.Tuple2[L, R], V, V, ReturnOne, ReadOnly, UniDir, Err]

BinaryOpE returns an Operation version of the given operator function. This constructor is a convenience wrapper for Operator with a simpler expression parameter.

The following additional constructors are available:

Example
customDivide := BinaryOpE(func(ctx context.Context, left, right float64) (float64, error) {
	if right == 0 {
		return 0, errors.New("divide by 0")
	}
	return left / right, nil
}, "/")

data := []float64{10, 20}

var overResult []float64
overResult, err := Modify(TraverseSlice[float64](), OpT2Bind(customDivide, 2), data)
fmt.Println(overResult, err)
Output:

[5 10] <nil>

func BitAnd

func BitAnd[A Integer](right A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

BitAnd returns an Operation that applies a bitwise and to the given value.

See:

  • BitOr for the bitwise or operator
  • BitXor for the bitwise exclusive or operator
  • BitNot for the bitwise not operator
Example
data := []int{
	0b000,
	0b001,
	0b010,
	0b011,
	0b100,
	0b101,
	0b110,
	0b111,
}

optic := TraverseSlice[int]()

var viewResult []int = MustGet(SliceOf(Filtered(optic, Compose(BitAnd(0b010), Ne(0))), len(data)), data)
fmt.Println(viewResult)

var overResult []int = MustModify(optic, BitAnd(0b010), data)
fmt.Println(overResult)

// Getters are optics and can be composed.
// This composition ands with 0b010 and then ors with 0b001
var composedResult []int = MustModify(optic, Compose(BitAnd(0b010), BitOr(0b001)), data)
fmt.Println(composedResult)
Output:

[2 3 6 7]
[0 0 2 2 0 0 2 2]
[1 1 3 3 1 1 3 3]

func BitAndT2

func BitAndT2[A Integer]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

BitAndT2 returns an BinaryOp that applies a bitwise and to the given values.

See:

Example
data := []int{
	0b1101,
	0b1011,
	0b1111,
}

optic := Reduce(
	TraverseSlice[int](),
	AsReducer(
		0b1111,
		BitAndT2[int](),
	),
)

viewResult, ok := MustGetFirst(optic, data)
fmt.Println(viewResult, ok)
Output:

9 true

func BitNot

func BitNot[A Integer]() Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

BitNot returns an Operation that applies a bitwise not.

See:

  • BitAnd for the bitwise and operator
  • BitOr for he bitwise or operator
  • BitXor for the bitwise exclusive or operator
Example
data := []int{
	0b000,
	0b001,
	0b010,
	0b011,
	0b100,
	0b101,
	0b110,
	0b111,
}

optic := TraverseSlice[int]()

var overResult []int = MustModify(optic, BitNot[int](), data)
fmt.Println(overResult)

// Getters are optics and can be composed.
// This composition ands with 0b010 and then nots the result
var composedResult []int = MustModify(optic, Compose(BitAnd(0b010), BitNot[int]()), data)
fmt.Println(composedResult)
Output:

[-1 -2 -3 -4 -5 -6 -7 -8]
[-1 -1 -3 -3 -1 -1 -3 -3]

func BitOr

func BitOr[A Integer](right A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

BitOr returns an Operation that applies a bitwise or to the given value.

See:

  • BitAnd for the bitwise and operator
  • BitXor for the bitwise exclusive or operator
  • BitNot for the bitwise not operator
Example
data := []int{
	0b000,
	0b001,
	0b010,
	0b011,
	0b100,
	0b101,
	0b110,
	0b111,
}

optic := TraverseSlice[int]()

var overResult []int = MustModify(optic, BitOr(0b010), data)
fmt.Println(overResult)

// Getters are optics and can be composed.
// This composition ands with 0b010 and then ors with 0b001
var composedResult []int = MustModify(optic, Compose(BitAnd(0b010), BitOr(0b001)), data)
fmt.Println(composedResult)
Output:

[2 3 2 3 6 7 6 7]
[1 1 3 3 1 1 3 3]

func BitOrT2

func BitOrT2[A Integer]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

BitOrT2 returns an BinaryOp that applies a bitwise or to the given values.

See:

  • BitOr for a unary version.
Example
data := []int{
	0b0001,
	0b0010,
	0b0100,
}

optic := Reduce(
	TraverseSlice[int](),
	AsReducer(
		0b0000,
		BitOrT2[int](),
	),
)

viewResult, ok := MustGetFirst(optic, data)
fmt.Println(viewResult, ok)
Output:

7 true

func BitXor

func BitXor[A Integer](right A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

BitXor returns an Operation that applies a bitwise xor to the given value.

See:

  • BitAnd for the bitwise and operator
  • BitOr for he bitwise or operator
  • BitNot for the bitwise not operator
Example
data := []int{
	0b000,
	0b001,
	0b010,
	0b011,
	0b100,
	0b101,
	0b110,
	0b111,
}

optic := TraverseSlice[int]()

var overResult []int = MustModify(optic, BitXor(0b010), data)
fmt.Println(overResult)

// Getters are optics and can be composed.
// This composition ands with 0b010 and then xors with 0b010
var composedResult []int = MustModify(optic, Compose(BitAnd(0b010), BitXor(0b010)), data)
fmt.Println(composedResult)
Output:

[2 3 0 1 6 7 4 5]
[2 2 0 0 2 2 0 0]

func BitXorT2

func BitXorT2[A Integer]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

BitXorT2 returns an BinaryOp that applies a bitwise xor to the given values.

See:

Example
data := []int{
	0b0101,
	0b1010,
	0b0100,
}

optic := Reduce(
	TraverseSlice[int](),
	AsReducer(
		0b0000,
		BitXorT2[int](),
	),
)

viewResult, ok := MustGetFirst(optic, data)
fmt.Println(viewResult, ok)
Output:

11 true

func CaptureMapString

func CaptureMapString(matchOn *regexp.Regexp, n int) Optic[lo.Tuple2[[]int, string], string, string, map[string]string, map[string]string, ReturnMany, ReadWrite, UniDir, Pure]

CaptureMapString returns an Traversal that focuses on the named capture groups of the given regexp.

Use an n value of -1 to match all the focuses.

The index is a tuple of the offsets of the capture groups and the full string match.

See: - MatchString for a for Traversal that focuses on the matches of a given regexp.. - CaptureString for a for Traversal that focuses on the indexed capture groups within a regexp.. - SplitString for a for Traversal that splits strings based on a regexp.

func CaptureString

func CaptureString(matchOn *regexp.Regexp, n int) Optic[lo.Tuple2[[]int, string], string, string, []string, []string, ReturnMany, ReadWrite, UniDir, Pure]

CaptureString returns an Traversal that focuses on the indexed capture groups of the given regexp.

Use an n value of -1 to match all the focuses.

The index is a tuple of the offsets of the capture groups and the full string match.

See: - MatchString for a for Traversal that focuses on the matches of a given regexp. - CaptureMapString for a for Traversal that focuses on the named capture groups within a regexp. - SplitString for a for Traversal that splits strings based on a regexp.

Example
data := "25/03/2025"

captures, ok := MustGetFirst(
	CaptureString(
		regexp.MustCompile(`(\d+)/(\d+)/(\d+)`),
		-1,
	),
	data,
)
fmt.Println(captures, ok)

var modifyResult string
modifyResult, err := Modify(
	Compose3(
		CaptureString(
			regexp.MustCompile(`(\d+)/(\d+)/(\d+)`),
			-1,
		),
		TraverseSlice[string](),
		ParseInt[int](10, 0),
	),
	Add(1),
	data,
)
fmt.Println(modifyResult, err)
Output:

[25 03 2025] true
26/4/2026 <nil>

func Catch

func Catch[I, S, T, A, B, RET, RW, DIR, ERR any, CT any, CB any, CRET TReturnOne, CRW any, CDIR any, CERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], catch Optic[I, error, CT, A, CB, CRET, CRW, CDIR, CERR]) Optic[I, S, T, A, B, RET, ReadOnly, UniDir, ERR]

The Catch combinator returns an optic that enables an error to be converted to a focus or to remain in error..

Note: Catch does not catch the context.DeadlineExceeded or context.Cancelled errors. See:

  • CatchP for a read write polymorphic version
  • Ignore for an optic that can ignore errors.
Example
optic := Catch(
	Compose(
		TraverseSlice[string](),
		ParseInt[int32](10, 32),
	),
	If(
		ErrorIs(strconv.ErrSyntax),
		EErr(Const[error](int32(-1))),
		Ro(Throw[int32]()),
	),
)

viewResult, err := Get(SliceOf(optic, 3), []string{"1", "two", "3"})
fmt.Println(viewResult, err)

viewResult, err = Get(SliceOf(optic, 3), []string{"1", "2147483648", "3"})
fmt.Println(viewResult, err)
Output:

[1 -1 3] <nil>
[] strconv.ParseInt: parsing "2147483648": value out of range
optic error path:
	ParseInt(10,32)
	Traverse
	Throw()
	Switch(Case(ErrorIs(invalid syntax) -> Const(-1))Default(Throw()))
	Catch(Traverse | ParseInt(10,32),Switch(Case(ErrorIs(invalid syntax) -> Const(-1))Default(Throw())),Throw())
	SliceOf(Catch(Traverse | ParseInt(10,32),Switch(Case(ErrorIs(invalid syntax) -> Const(-1))Default(Throw())),Throw()))

func CatchP

func CatchP[I, S, T, A, B, RET, RW, DIR, ERR any, CAT any, CAB any, CARET, CBRET TReturnOne, CARW any, CADIR any, CAERR, CBERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], catchA Optic[I, error, CAT, A, CAB, CARET, CARW, CADIR, CAERR], catchT Operation[error, T, CBRET, CBERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The CatchP combinator returns an optic that enables an error to be converted to a focus or to remain in error..

Note: Catch does not catch the context.DeadlineExceeded or context.Cancelled errors. See:

  • Catch for a read only non polymorphic version
  • Ignore for an optic that can ignore errors.
Example
optic := CatchP(
	Compose(
		TraverseSliceP[string, int32](),
		ParseIntP[int32](10, 32),
	),
	Ret1(Ro(EErr(If(
		ErrorIs(strconv.ErrSyntax),
		EErr(Const[error](int32(-1))),
		Ro(Throw[int32]()),
	)))),
	EErr(Const[error, []int32](nil)),
)

viewResult, err := Get(SliceOf(optic, 3), []string{"1", "two", "3"})
fmt.Println(viewResult, err)

modifyResult, err := Modify(optic, Mul[int32](2), []string{"1", "two", "3"})
fmt.Println(modifyResult, err)
Output:

[1 -1 3] <nil>
[] <nil>

func Chosen

func Chosen[A any]() Optic[ChosenSide, mo.Either[A, A], mo.Either[A, A], A, A, ReturnOne, ReadWrite, UniDir, Pure]

Chosen returns a Lens that focuses on the present element of a mo.Either. The index indicates which side was present.

Example
chosenLeft := MustGet(Chosen[int](), mo.Left[int, int](1))
fmt.Println(chosenLeft)

chosenRight := MustGet(Chosen[int](), mo.Right[int, int](1))
fmt.Println(chosenRight)

//As the left value is chosen. a new Left is returned with the set value
setChosen := MustSet(Chosen[int](), 2, mo.Left[int, int](1))
fmt.Println(setChosen)
Output:

1
1
{true 2 0}

func Clamp

func Clamp[A cmp.Ordered](min A, max A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Clamp returns an Operation that constrains the focused value between min and max.

Example
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var result []int = MustModify(
	TraverseSlice[int](),
	Clamp(3, 6),
	data,
)
fmt.Println(result)
Output:

[3 3 3 4 5 6 6 6 6 6]

func Coalesce

func Coalesce[I, S, T, A, B, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2 any](o1 Optic[I, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, T, A, B, RET2, RW2, DIR2, ERR2]) Optic[I, S, T, A, B, CompositionTree[RET1, RET2], CompositionTree[RW1, RW2], UniDir, CompositionTree[ERR1, ERR2]]

func Coalesce3

func Coalesce3[I, S, T, A, B, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2, RET3, RW3, DIR3, ERR3 any](o1 Optic[I, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, T, A, B, RET2, RW2, DIR2, ERR2], o3 Optic[I, S, T, A, B, RET3, RW3, DIR3, ERR3]) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[CompositionTree[RW1, RW2], RW3], UniDir, CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]

func Coalesce4

func Coalesce4[I, S, T, A, B, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2, RET3, RW3, DIR3, ERR3, RET4, RW4, DIR4, ERR4 any](o1 Optic[I, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, T, A, B, RET2, RW2, DIR2, ERR2], o3 Optic[I, S, T, A, B, RET3, RW3, DIR3, ERR3], o4 Optic[I, S, T, A, B, RET4, RW4, DIR4, ERR4]) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], UniDir, CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]]]

func CoalesceN

func CoalesceN[I, S, T, A, B, RET, RW, DIR, ERR any](o ...Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, UniDir, ERR]

The CoalesceN combinator focuses on the elements of the first optic that yields at least one element.

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
index5 := Index(TraverseMap[int, string](), 5)
index3 := Index(TraverseMap[int, string](), 3)

failingOptic := CoalesceN(index5, index3)

//There is no element 5 in the map so the index3 optic is used instead.
viewResult, found := MustGetFirst(failingOptic, data)
fmt.Println(viewResult, found) //gamma

var modifyResult map[int]string = MustModify(failingOptic, Op(strings.ToUpper), data)
fmt.Println(modifyResult)

//Once we add an element at index 5 then the index5 will match
data[5] = "epsilon"

viewResult, found = MustGetFirst(failingOptic, data)
fmt.Println(viewResult, found) //epsilon

modifyResult = MustModify(failingOptic, Op(strings.ToUpper), data)
fmt.Println(modifyResult)
Output:

gamma true
map[1:alpha 2:beta 3:GAMMA 4:delta]
epsilon true
map[1:alpha 2:beta 3:gamma 4:delta 5:EPSILON]

func ColFocusErr

func ColFocusErr[I, J, S, T, A, B, RET, RW, DIR, ERR any, OAERR, OBERR any](o Optic[J, S, T, Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, ERR]) Optic[J, S, T, Collection[I, A, Err], Collection[I, B, Err], RET, RW, DIR, Err]

ColFocusErr returns the input Optic with Err as the focus Collection SERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

Example
data := lo.T2("alpha", []string{"3", "2", "1"})

//The Sort may generate an error in the collection during sorting.
//The Collection has a CompositionTree asit's ERR.
sort := OrderedCol[int](
	OrderBy(
		ParseInt[int](10, 0),
	),
)

sortSlice := Compose3(
	ColFocusErr(SliceToCol[string]()), //ColFocusErr pure conversion from slice to collection to focus on collection Err
	sort,
	ColSourceErr(AsReverseGet(SliceToCol[string]())), //ColSourceErr pure conversion from collection to slice to source from a collection Err
)

res, err := Modify(
	T2B[string, []string](),
	sortSlice,
	data,
)

fmt.Println(res, err)
Output:

{alpha [1 2 3]} <nil>

func ColFocusPure

func ColFocusPure[I, J, S, T, A, B, RET, RW, DIR, ERR any, OAERR, OBERR TPure](o Optic[J, S, T, Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, ERR]) Optic[J, S, T, Collection[I, A, Pure], Collection[I, B, Pure], RET, RW, DIR, Pure]

ColFocusPure returns the pure input Optic with the given focus Collection ERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

  • ColFocusPure for a non polymorphic version
  • [ColSourceFocusPureP] for a version that modifies both the source and focus Collection ERR.
  • [ColSourceErrP] for a version that only modifies the source Collection ERR
  • ColSourceErr for a version that modifies any source Collection to Err
Example
data := lo.T2("alpha", []string{"3", "2", "1"})

//The Sort may generate an error in the collection during sorting.
//The Collection has a CompositionTree asit's ERR.
sort := OrderedCol[int](
	OrderBy(
		ParseInt[int](10, 0),
	),
)

sortSlice := Compose3(
	ColFocusErr(SliceToCol[string]()), //ColFocusPure pure conversion from slice to collection to focus on collection Err
	sort,
	ColSourceErr(AsReverseGet(SliceToCol[string]())), //ColSourceErr pure conversion from collection to slice to source from a collection Err
)

res, err := Modify(
	T2B[string, []string](),
	sortSlice,
	data,
)

fmt.Println(res, err)
Output:

{alpha [1 2 3]} <nil>

func ColOf

func ColOf[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR]) Optic[Void, S, T, Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, RW, UniDir, ERR]

The ColOf combinator focuses on a Collection of all the elements in the given optic.

Under modification this collection can be modified and will be rebuilt into the original data structure. If the modified collection contains fewer elements the result will use values from the original source. If the modified collection contains more elements they will be ignored.

See:

  • ColOfP for a polymorphic version.
  • [ColyTypeOf] for a version that operates on concrete collection types
Example
data := map[int][]string{
	1: []string{"gamma", "beta"},
	2: []string{"alpha", "delta"},
}

optic := ColOf(
	EPure(Compose(
		TraverseMap[int, []string](),
		TraverseSlice[string](),
	)),
)

var viewResult Collection[int, string, Pure] = MustGet(optic, data)
fmt.Println(viewResult)

op := OrderedCol[int](OrderBy(Identity[string]()))

modifyResult := MustModify(optic, op, data)
fmt.Println(modifyResult)
Output:

Col[0:gamma 1:beta 0:alpha 1:delta]
map[1:[alpha beta] 2:[delta gamma]]

func ColOfP

func ColOfP[I, S, T, A, B, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[Void, S, T, Collection[I, A, Err], Collection[I, B, Err], ReturnOne, RW, UniDir, Err]

The ColOfP combinator focuses on a polymorphic Collection of all the elements in the given optic.

Under modification this collection can be modified and will be rebuilt into the original data structure. If the modified collection contains fewer elements then ErrUnsafeMissingElement will be returned If the modified collection contains more elements they will be ignored.

See:

  • ColOf for a safe non polymorphic version.
  • [ColyTypeOfP] for a version that operates on concrete collection types
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := ColOfP(TraverseMapP[int, string, int]())

var viewResult Collection[int, string, Err]
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, OpE(func(ctx context.Context, focus Collection[int, string, Err]) (Collection[int, int, Err], error) {
	var modified []ValueE[int]
	seq, err := Get(SeqEOf(TraverseColE[int, string, Err]()), focus)
	if err != nil {
		return nil, err
	}
	for v := range seq {
		str, err := v.Get()
		modified = append(modified, ValE(len(str), err))
	}

	return ValColE(modified...), nil
}), data)
fmt.Println(modifyResult, err)
Output:

Col[1:alpha 2:beta 3:gamma 4:delta] <nil>
map[1:5 2:4 3:5 4:5] <nil>

func ColSourceErr

func ColSourceErr[I, J, S, T, A, B, RET, RW, DIR, ERR any, SERR, TERR any](o Optic[J, Collection[I, S, SERR], Collection[I, T, TERR], A, B, RET, RW, DIR, ERR]) Optic[J, Collection[I, S, Err], Collection[I, T, Err], A, B, RET, RW, DIR, Err]

ColSourceErr returns the input Optic with Err as the source Collection SERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

Example
data := lo.T2("alpha", []string{"3", "2", "1"})

//The Sort may generate an error in the collection during sorting.
//The Collectionon has a CompositionTree asit's ERR.
sort := OrderedCol[int](
	OrderBy(
		ParseInt[int](10, 0),
	),
)

sortSlice := Compose3(
	ColFocusErr(SliceToCol[string]()), //ColFocusErr pure conversion from slice to collection to focus on collection Err
	sort,
	ColSourceErr(AsReverseGet(SliceToCol[string]())), //ColSourceErr pure conversion from collection to slice to source from a collection Err
)

res, err := Modify(
	T2B[string, []string](),
	sortSlice,
	data,
)

fmt.Println(res, err)
Output:

{alpha [1 2 3]} <nil>

func ColSourceFocusErr

func ColSourceFocusErr[I, J, S, T, A, B, RET, RW, DIR, ERR any, OSERR, OTERR, OAERR, OBERR any](o Optic[J, Collection[I, S, OSERR], Collection[I, T, OTERR], Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, ERR]) Optic[J, Collection[I, S, Err], Collection[I, T, Err], Collection[I, A, Err], Collection[I, B, Err], RET, RW, DIR, Err]

ColSourceFocusErr returns the input Optic with Err as the source Collection SERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

Example
data := []string{"3", "beta", "2"}

//The Sort may generate an error in the collection during sorting.
var sort Optic[Void, Collection[int, string, Err], Collection[int, string, Err], Collection[int, string, Err], Collection[int, string, Err], ReturnOne, ReadWrite, UniDir, Err] = OrderedCol[int](
	OrderBy(
		ParseInt[int](10, 0),
	),
)

//FilteredCol however generates a pure collection.
var filteredPure Optic[Void, Collection[int, string, Pure], Collection[int, string, Pure], Collection[int, string, Pure], Collection[int, string, Pure], ReturnOne, ReadWrite, UniDir, Pure] = FilteredCol[int](Ne("beta"))

//ColSourceFocusPure converts the Pure Collections to the given ERR type.
var filteredErr Optic[Void, Collection[int, string, Err], Collection[int, string, Err], Collection[int, string, Err], Collection[int, string, Err], ReturnOne, ReadWrite, UniDir, Err] = ColSourceFocusErr(filteredPure)

//res, err := Modify(
//	ColFocusErr(SliceToCol[string]()),
//	Compose(
//		filteredPure,
//		sort, //<----- Compile error here, sort expects a Collection[int,string,Err] but filteredPure provides Collection[int,string,Pure]
//	),
//	data,
//)

res, err := Modify(
	ColFocusErr(SliceToCol[string]()),
	Compose(
		filteredErr,
		sort,
	),
	data,
)

fmt.Println(res, err)
Output:

[2 3] <nil>

func ColSourceFocusPure

func ColSourceFocusPure[I, J, S, T, A, B, RET, RW, DIR, ERR any, OSERR, OTERR, OAERR, OBERR TPure](o Optic[J, Collection[I, S, OSERR], Collection[I, T, OTERR], Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, ERR]) Optic[J, Collection[I, S, Pure], Collection[I, T, Pure], Collection[I, A, Pure], Collection[I, B, Pure], RET, RW, DIR, Pure]

ColSourceFocusPure returns the input Optic with the SERR as the source and focus Collection ERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

func ColSourcePure

func ColSourcePure[I, J, S, T, A, B, RET, RW, DIR any, ERR TPure, OSERR TPure](o Optic[J, Collection[I, S, OSERR], Collection[I, T, OSERR], A, B, RET, RW, DIR, ERR]) Optic[J, Collection[I, S, Pure], Collection[I, T, Pure], A, B, RET, RW, DIR, Pure]

ColSourcePure returns the pure input Optic with the SERR as the source Collection ERR.

This function is intended when combinining optics that use a mix of Pure and Err [Collection]s.

See:

Example
data := lo.T2("alpha", []string{"3", "2", "1"})

//The Sort may generate an error in the collection during sorting.
//The Collection has a CompositionTree asit's ERR.
sort := OrderedCol[int](
	OrderBy(
		ParseInt[int](10, 0),
	),
)

sortSlice := Compose3(
	ColFocusErr(SliceToCol[string]()), //ColFocusErr pure conversion from slice to collection to focus on collection Err
	sort,
	ColSourceErr(AsReverseGet(SliceToCol[string]())), //ColSourcePure pure conversion from collection to slice to source from a collection Err
)

res, err := Modify(
	T2B[string, []string](),
	sortSlice,
	data,
)

fmt.Println(res, err)
Output:

{alpha [1 2 3]} <nil>

func ColToColType

func ColToColType[I, S, T, A, B any, ERR any](s CollectionType[I, S, T, A, B, ERR]) Optic[Void, Collection[I, A, ERR], Collection[I, B, ERR], S, T, ReturnOne, ReadWrite, BiDir, ERR]

ColToColType returns an Iso that converts a Collection to the concrete collection type ([]string])

This provides easy access to Collection operations like Reversed without needing to use [makecolop] to generate the specialized collection operations.

See:

Example
colType := ColType(
	SliceToCol[string](),
	TraverseSlice[string](),
)

data := []string{"gamma", "beta", "alpha"}

optic := Compose4(
	ColTypeToCol(colType),        //[]string --> Collection[int,string,Pure]
	FilteredCol[int](Ne("beta")), //Collection[int,string,Pure]
	ReversedCol[int, string](),   //Collection[int,string,Pure]
	ColToColType(colType),        // Collection[int,string,Pure] --> []string
)

var res []string = MustGet(
	optic,
	data,
)

fmt.Println(res)
Output:

[alpha gamma]

func ColToMap

func ColToMap[K comparable, S any]() Optic[Void, Collection[K, S, Pure], Collection[K, S, Pure], map[K]S, map[K]S, ReturnOne, ReadWrite, BiDir, Pure]

ColToMap returns an Iso that converts from a Map like collection to a Map

See:

  • ColToMapP for a polymorphic version.

func ColToMapP

func ColToMapP[K comparable, S, T any]() Optic[Void, Collection[K, S, Pure], Collection[K, T, Pure], map[K]S, map[K]T, ReturnOne, ReadWrite, BiDir, Pure]

ColToMapP returns a polymorphic Iso that converts from a Map like collection to a Map

See:

  • ColToMap for a no polymorphic version.

func ColToSlice

func ColToSlice[A any]() Optic[Void, Collection[int, A, Pure], Collection[int, A, Pure], []A, []A, ReturnOne, ReadWrite, BiDir, Pure]

ColToSlice returns an Iso that converts from a Slice like collection to a Slice

See:

  • ColToSliceP for a polymorphic version.

func ColToSliceP

func ColToSliceP[A, B any]() Optic[Void, Collection[int, A, Pure], Collection[int, B, Pure], []A, []B, ReturnOne, ReadWrite, BiDir, Pure]

ColToSliceP returns a polymorphic Iso that converts from a Slice like collection to a Slice

See:

  • ColToSlice for a no polymorphic version.

func ColToString

ColToString returns an Iso that converts from a String like collection to a String

See:

  • ColToStringP for a polymorphic version.

func ColToStringP

ColToStringP returns a polymorphic Iso that converts from a String like collection to a String

See:

  • ColToString for a no polymorphic version.

func ColTypeOf

func ColTypeOf[I, SC, TC, ERR, A, S, T, ORET, ORW, ODIR any](ct CollectionType[I, SC, TC, A, A, ERR], o Optic[I, S, T, A, A, ORET, ORW, ODIR, ERR]) Optic[Void, S, T, TC, TC, ReturnOne, ORW, UniDir, ERR]

The ColTypeOf combinator focuses on the concrete collection of all the elements in the given optic.

Under modification this collection can be modified and will be rebuilt into the original data structure. If the modified collection contains fewer elements the result will use values from the original source. If the modified collection contains more elements they will be ignored.

See:

Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := ColTypeOf(
	MapColType[int, string](),
	TraverseSlice[string](),
)

var viewResult map[int]string = MustGet(optic, data)
fmt.Println(viewResult)
Output:

map[0:alpha 1:beta 2:gamma 3:delta]

func ColTypeOfP

func ColTypeOfP[I, SC, TC, ERR, A, B, S, T, ORET, ORW, ODIR any](ct CollectionType[I, SC, TC, A, B, ERR], o Optic[I, S, T, A, B, ORET, ORW, ODIR, ERR]) Optic[Void, S, T, SC, TC, ReturnOne, ORW, UniDir, Err]

The ColTypeOfP combinator focuses on a polymorphic concrete collection of all the elements in the given optic.

Under modification this collection can be modified and will be rebuilt into the original data structure. If the modified collection contains fewer elements then ErrUnsafeMissingElement will be returned If the modified collection contains more elements they will be ignored.

See:

  • ColOf for a safe non polymorphic version.
  • [ColyTypeOfP] for a version that operates on concrete collection types
Example
data := []string{"1", "2", "3", "4"}

optic := ColTypeOfP(
	MapColTypeP[int, string, int](),
	TraverseSliceP[string, int](),
)

var viewResult map[int]string
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

var modifyResult []int
modifyResult, err = Modify(
	optic,
	AsModify(
		TraverseMapP[int, string, int](),
		ParseIntP[int](10, 0),
	),
	data,
)
fmt.Println(modifyResult, err)
Output:

map[0:1 1:2 2:3 3:4] <nil>
[1 2 3 4] <nil>

func ColTypeOp

func ColTypeOp[I, J, S, T, A, B any, RET TReturnOne, RW any, DIR any, ERR any](s CollectionType[I, S, T, A, B, ERR], o Optic[J, Collection[I, A, ERR], Collection[I, B, ERR], Collection[I, B, ERR], Collection[I, B, ERR], RET, RW, DIR, ERR]) Optic[J, S, T, T, T, ReturnOne, RW, DIR, ERR]

ColTypeOp returns an optic that applies the given collection operation optic to the given collection. The source and focus are the underlying collection type

Example
sliceCol := SliceColTypeP[string, string]()

//ColOp converts a col op into a col op for our specific collection
stringReversed := ColTypeOp(sliceCol, ReversedCol[int, string]())

result := MustGet(stringReversed, []string{"alpha", "beta", "gamma", "delta"})

fmt.Println(result)
Output:

[delta gamma beta alpha]

func ColTypeToCol

func ColTypeToCol[I, S, T, A, B any, ERR any](s CollectionType[I, S, T, A, B, ERR]) Optic[Void, S, T, Collection[I, A, ERR], Collection[I, B, ERR], ReturnOne, ReadWrite, BiDir, ERR]

ColTypeToCol returns an Iso that converts the concrete collection type ([]string]) to a Collection

This provides easy access to Collection operations like Reversed without needing to use [makecolop] to generate the specialized collection operations.

See:

Example
colType := ColType(
	SliceToCol[string](),
	TraverseSlice[string](),
)

data := []string{"gamma", "beta", "alpha"}

optic := ColTypeToCol(colType) //[]string --> Collection[int,string,Pure]

var res []string = MustModify(
	optic,
	ReversedCol[int, string](), //Collection[int,string,Pure]
	data,
)

fmt.Println(res)
Output:

[alpha beta gamma]

func CombiColFocusErr

func CombiColFocusErr[ERR, I, J, S, T, A, B, RET, RW, DIR any, OERR, OAERR, OBERR TPure](o Optic[J, S, T, Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, OERR]) Optic[J, S, T, Collection[I, A, ERR], Collection[I, B, ERR], RET, RW, DIR, ERR]

func CombiColSourceErr

func CombiColSourceErr[ERR any, I, J, S, T, A, B, RET, RW, DIR any, OERR, OSERR, OTERR TPure](o Optic[J, Collection[I, S, OSERR], Collection[I, T, OTERR], A, B, RET, RW, DIR, OERR]) Optic[J, Collection[I, S, ERR], Collection[I, T, ERR], A, B, RET, RW, DIR, ERR]

func CombiColSourceFocusErr

func CombiColSourceFocusErr[SERR, I, J, S, T, A, B, RET, RW, DIR any, ERR, OSERR, OTERR, OAERR, OBERR TPure](o Optic[J, Collection[I, S, OSERR], Collection[I, T, OTERR], Collection[I, A, OAERR], Collection[I, B, OBERR], RET, RW, DIR, ERR]) Optic[J, Collection[I, S, SERR], Collection[I, T, SERR], Collection[I, A, SERR], Collection[I, B, SERR], RET, RW, DIR, SERR]

func CombiDir

func CombiDir[DIR any, I, S, T, A, B any, RET any, RW any, ERR any, ODIR TBiDir](o Optic[I, S, T, A, B, RET, RW, ODIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

func CombiEErr

func CombiEErr[ERR any, I, S, T, A, B any, RET any, RW any, DIR any, OERR TPure](o Optic[I, S, T, A, B, RET, RW, DIR, OERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]
Example
package main

import (
	"fmt"

	. "github.com/spearson78/go-optic"
)

func FilteredColIExample[I comparable, J, S, T, A, RET, RW, DIR, ERR any](o Optic[J, S, T, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], index I) Optic[Void, S, T, Collection[I, A, ERR], Collection[I, A, ERR], RET, ReadOnly, UniDir, ERR] {
	return RetL(Ro(Ud(EErrMerge(Compose(
		o,
		FilteredColI(
			CombiEErr[ERR](EqI[A](index)),
			IxMatchComparable[I](),
		),
	)))))
}

func main() {

	data := []string{"alpha", "beta", "gamma", "delta"}

	optic := FilteredColIExample(
		SliceToCol[string](),
		1,
	)

	res := MustGet(optic, data)
	fmt.Println(res)

}
Output:

Col[1:beta]

func CombiGetMod

func CombiGetMod[RW, ERR any, I, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	modify func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, RW, UniDir, ERR]

func CombiGetter

func CombiGetter[ERR any, I, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, ReadOnly, UniDir, ERR]

func CombiIso

func CombiIso[RW, DIR, ERR, S, T, A, B any](
	getter func(ctx context.Context, source S) (A, error),
	reverse func(ctx context.Context, focus B) (T, error),
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, RW, BiDir, ERR]

func CombiIsoMod

func CombiIsoMod[RW, DIR, ERR any, I, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	modify func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error),
	reverse func(ctx context.Context, focus B) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, RW, DIR, ERR]

func CombiIteration

func CombiIteration[RET, ERR, I, S, T, A, B any](
	iterate func(ctx context.Context, source S) SeqIE[I, A],
	lengthGetter LengthGetterFunc[S],
	ixget func(ctx context.Context, index I, source S) SeqIE[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, RET, ReadOnly, UniDir, ERR]

func CombiLens

func CombiLens[RW, ERR any, I, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	set func(ctx context.Context, focus B, source S) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, RW, UniDir, ERR]

func CombiPrism

func CombiPrism[RW, DIR, ERR any, I, S, T, A, B any](
	match func(ctx context.Context, source S) (mo.Either[T, ValueI[I, A]], error),
	embed func(ctx context.Context, focus B) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnMany, RW, DIR, ERR]

func CombiRw

func CombiRw[RW any, I, S, T, A, B any, RET any, DIR any, ERR any, ORW TReadWrite](o Optic[I, S, T, A, B, RET, ORW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

func CombiTraversal

func CombiTraversal[RET, RW, ERR, I, S, T, A, B any](
	iterate func(ctx context.Context, source S) SeqIE[I, A],
	lengthGetter LengthGetterFunc[S],
	modify func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error),
	ixget func(ctx context.Context, index I, source S) SeqIE[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, RET, RW, UniDir, ERR]
Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := FirstExample(TraverseSlice[string]())

result := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(result)
Output:

[ALPHA beta gamma delta]

func Compose

func Compose[I, J, S, T, A, B, C, D, RETI, RETJ any, RWI, RWJ any, DIRI, DIRJ any, ERRI, ERRJ any](left Optic[I, S, T, A, B, RETI, RWI, DIRI, ERRI], right Optic[J, A, B, C, D, RETJ, RWJ, DIRJ, ERRJ]) Optic[J, S, T, C, D, CompositionTree[RETI, RETJ], CompositionTree[RWI, RWJ], CompositionTree[DIRI, DIRJ], CompositionTree[ERRI, ERRJ]]

Compose returns an Optic composed of the 2 input optics.

Composition combines the 2 optics such that the output of the left is connected to the input of the right with the result using the index of the right input. The composed optic is compatible with both view and modify actions.

See:

  • ComposeLeft for a version that returns an optic using the left index.
  • ComposeBoth for a version that returns an optic using both indices combined together.
  • ComposeI for a version that returns a custom index.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

If you are implementing a Combinator then it is recommended to use either a condensing combinator (Ret1,RetM) or condensing compose e.g. [ComposeRet1] , [ComposeRetM]

Example
data := []lo.Tuple2[string, int]{
	lo.T2("alpha", 1),
	lo.T2("beta", 2),
	lo.T2("gamma", 3),
	lo.T2("delta", 4),
}

//In this example we will fully specify the types of the optics
//This is is not necessary in normal usage.

//The left optic we will use in the compose
var leftOptic Optic[
	int,                      //Index Type
	[]lo.Tuple2[string, int], //Source Type
	[]lo.Tuple2[string, int], //Result Type
	lo.Tuple2[string, int],   //Focus type
	lo.Tuple2[string, int],   //Result focus type
	ReturnMany,               //Return type
	ReadWrite,                //ReadWrite type
	UniDir,                   //Dir type
	Pure,                     //Error type
] = TraverseSlice[lo.Tuple2[string, int]]()

//This optic will receive a slice of tuples and focus on the individual tuples.
//Under modification it will allow the tuple to be edited and combine the edits
//together into a slice of tuples.

//The right optic we will use in the compose
var rightOptic Optic[
	int,                    //Index Type
	lo.Tuple2[string, int], //Source Type
	lo.Tuple2[string, int], //Result Type
	string,                 //Focus type
	string,                 //Result focus type
	ReturnOne,              //Return type
	ReadWrite,              //ReadWrite type
	UniDir,                 //Dir type
	Pure,                   //Error type
] = T2A[string, int]()

//This optic will receive a tuple and focus on the first element.
//Under modification it will allow the first element to be edited
//and the result is a tuple with a modified first element.

var composedOptic Optic[
	int,                                    //Index Type
	[]lo.Tuple2[string, int],               //Source Type
	[]lo.Tuple2[string, int],               //Result Type
	string,                                 //Focus type
	string,                                 //Result focus type
	CompositionTree[ReturnMany, ReturnOne], //Return type
	CompositionTree[ReadWrite, ReadWrite],  //ReadWrite type
	CompositionTree[UniDir, UniDir],        //Dir type
	CompositionTree[Pure, Pure],            //Error type
] = Compose(leftOptic, rightOptic)

//The composed optic will receive a slice of tuples and focus on the first element of each tuple.
//Under modification it will allow the first element to be edited
//and the result is slice of tuples with a modified first element.

//Note the result index is the Void index from the right optic
//See ICompose for the ability to define a different index.

//MustListOf retrieves the focuses and converts them to a slice
var listOfResult []string = MustGet(SliceOf(composedOptic, len(data)), data)
fmt.Println(listOfResult) //[alpha beta gamma delta]

//Over applies the strings.ToUpper function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the first elements are in upper case the second elements are unmodified.
var overResult []lo.Tuple2[string, int] = MustModify(composedOptic, Op(strings.ToUpper), data)
fmt.Println(overResult) //[{ALPHA 1} {BETA 2} {GAMMA 3} {DELTA 3}]
Output:

[alpha beta gamma delta]
[{ALPHA 1} {BETA 2} {GAMMA 3} {DELTA 4}]

func Compose3

func Compose3[I1 any, I2 any, I3 any, S any, T any, A any, B any, C any, D any, E any, F any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3]) Optic[I3, S, T, E, F, CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[CompositionTree[RW1, RW2], RW3], CompositionTree[CompositionTree[DIR1, DIR2], DIR3], CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]

Compose3 returns an Optic composed of the 3 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose4

func Compose4[I1 any, I2 any, I3 any, I4 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4]) Optic[I4, S, T, G, H, CompositionTree[CompositionTree[RET1, RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], CompositionTree[CompositionTree[DIR1, DIR2], CompositionTree[DIR3, DIR4]], CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]]]

Compose4 returns an Optic composed of the 4 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose5

func Compose5[I1 any, I2 any, I3 any, I4 any, I5 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5]) Optic[I5, S, T, J, K, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[RET4, RET5]], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], CompositionTree[RW4, RW5]], CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], DIR3], CompositionTree[DIR4, DIR5]], CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], ERR3], CompositionTree[ERR4, ERR5]]]

Compose5 returns an Optic composed of the 5 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose6

func Compose6[I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, L any, M any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5], o6 Optic[I6, J, K, L, M, RET6, RW6, DIR6, ERR6]) Optic[I6, S, T, L, M, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[CompositionTree[RET4, RET5], RET6]], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], CompositionTree[CompositionTree[RW4, RW5], RW6]], CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], DIR3], CompositionTree[CompositionTree[DIR4, DIR5], DIR6]], CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], ERR3], CompositionTree[CompositionTree[ERR4, ERR5], ERR6]]]

Compose6 returns an Optic composed of the 6 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose7

func Compose7[I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, L any, M any, N any, O any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5], o6 Optic[I6, J, K, L, M, RET6, RW6, DIR6, ERR6], o7 Optic[I7, L, M, N, O, RET7, RW7, DIR7, ERR7]) Optic[I7, S, T, N, O, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[RET5, RET6], RET7]], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], CompositionTree[CompositionTree[RW5, RW6], RW7]], CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], CompositionTree[DIR3, DIR4]], CompositionTree[CompositionTree[DIR5, DIR6], DIR7]], CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]], CompositionTree[CompositionTree[ERR5, ERR6], ERR7]]]

Compose7 returns an Optic composed of the 7 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose8

func Compose8[I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, I8 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, L any, M any, N any, O any, P any, Q any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any, RET8 any, RW8 any, DIR8 any, ERR8 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5], o6 Optic[I6, J, K, L, M, RET6, RW6, DIR6, ERR6], o7 Optic[I7, L, M, N, O, RET7, RW7, DIR7, ERR7], o8 Optic[I8, N, O, P, Q, RET8, RW8, DIR8, ERR8]) Optic[I8, S, T, P, Q, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[RET5, RET6], CompositionTree[RET7, RET8]]], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], CompositionTree[CompositionTree[RW5, RW6], CompositionTree[RW7, RW8]]], CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], CompositionTree[DIR3, DIR4]], CompositionTree[CompositionTree[DIR5, DIR6], CompositionTree[DIR7, DIR8]]], CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]], CompositionTree[CompositionTree[ERR5, ERR6], CompositionTree[ERR7, ERR8]]]]

Compose8 returns an Optic composed of the 8 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose9

func Compose9[I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, I8 any, I9 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, L any, M any, N any, O any, P any, Q any, R any, U any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any, RET8 any, RW8 any, DIR8 any, ERR8 any, RET9 any, RW9 any, DIR9 any, ERR9 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5], o6 Optic[I6, J, K, L, M, RET6, RW6, DIR6, ERR6], o7 Optic[I7, L, M, N, O, RET7, RW7, DIR7, ERR7], o8 Optic[I8, N, O, P, Q, RET8, RW8, DIR8, ERR8], o9 Optic[I9, P, Q, R, U, RET9, RW9, DIR9, ERR9]) Optic[I9, S, T, R, U, CompositionTree[CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[RET4, RET5]], CompositionTree[CompositionTree[RET6, RET7], CompositionTree[RET8, RET9]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], CompositionTree[RW4, RW5]], CompositionTree[CompositionTree[RW6, RW7], CompositionTree[RW8, RW9]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], DIR3], CompositionTree[DIR4, DIR5]], CompositionTree[CompositionTree[DIR6, DIR7], CompositionTree[DIR8, DIR9]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], ERR3], CompositionTree[ERR4, ERR5]], CompositionTree[CompositionTree[ERR6, ERR7], CompositionTree[ERR8, ERR9]]]]

Compose9 returns an Optic composed of the 9 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func Compose10

func Compose10[I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, I8 any, I9 any, I10 any, S any, T any, A any, B any, C any, D any, E any, F any, G any, H any, J any, K any, L any, M any, N any, O any, P any, Q any, R any, U any, V any, W any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any, RET8 any, RW8 any, DIR8 any, ERR8 any, RET9 any, RW9 any, DIR9 any, ERR9 any, RET10 any, RW10 any, DIR10 any, ERR10 any](o1 Optic[I1, S, T, A, B, RET1, RW1, DIR1, ERR1], o2 Optic[I2, A, B, C, D, RET2, RW2, DIR2, ERR2], o3 Optic[I3, C, D, E, F, RET3, RW3, DIR3, ERR3], o4 Optic[I4, E, F, G, H, RET4, RW4, DIR4, ERR4], o5 Optic[I5, G, H, J, K, RET5, RW5, DIR5, ERR5], o6 Optic[I6, J, K, L, M, RET6, RW6, DIR6, ERR6], o7 Optic[I7, L, M, N, O, RET7, RW7, DIR7, ERR7], o8 Optic[I8, N, O, P, Q, RET8, RW8, DIR8, ERR8], o9 Optic[I9, P, Q, R, U, RET9, RW9, DIR9, ERR9], o10 Optic[I10, R, U, V, W, RET10, RW10, DIR10, ERR10]) Optic[I10, S, T, V, W, CompositionTree[CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], CompositionTree[RET4, RET5]], CompositionTree[CompositionTree[CompositionTree[RET6, RET7], RET8], CompositionTree[RET9, RET10]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], CompositionTree[RW4, RW5]], CompositionTree[CompositionTree[CompositionTree[RW6, RW7], RW8], CompositionTree[RW9, RW10]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[DIR1, DIR2], DIR3], CompositionTree[DIR4, DIR5]], CompositionTree[CompositionTree[CompositionTree[DIR6, DIR7], DIR8], CompositionTree[DIR9, DIR10]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[ERR1, ERR2], ERR3], CompositionTree[ERR4, ERR5]], CompositionTree[CompositionTree[CompositionTree[ERR6, ERR7], ERR8], CompositionTree[ERR9, ERR10]]]]

Compose10 returns an Optic composed of the 10 input optics.

Composition combines the optics such that the output of each optic is connected to the inputs of the next using the rightmost index.

The composed optic is compatible with both view and modify actions.

See:

  • Compose for a version that takes 2 parameters.
  • Compose3 for a version that takes 3 parameters.
  • Compose4 for a version that takes 4 parameters.
  • Compose5 for a version that takes 5 parameters.
  • Compose6 for a version that takes 6 parameters.
  • Compose7 for a version that takes 7 parameters.
  • Compose8 for a version that takes 8 parameters.
  • Compose9 for a version that takes 9 parameters.
  • Compose10 for a version that takes 10 parameters.

func ComposeBoth

func ComposeBoth[I, J, S, T, A, B, C, D, RETI, RETJ, RWI, RWJ, DIRI, DIRJ, ERRI, ERRJ any](o1 Optic[I, S, T, A, B, RETI, RWI, DIRI, ERRI], o2 Optic[J, A, B, C, D, RETJ, RWJ, DIRJ, ERRJ]) Optic[lo.Tuple2[I, J], S, T, C, D, CompositionTree[RETI, RETJ], CompositionTree[RWI, RWJ], CompositionTree[DIRI, DIRJ], CompositionTree[ERRI, ERRJ]]

ComposeBoth returns an Optic composed of the 2 input optics using a combined left and right index in the result.

See:

  • Compose for a the general version that returns an optic using the right index.
  • ComposeLeft for a version that returns an optic using th left index.
  • ComposeI for a version that returns a custom index.

If you are implementing a Combinator then it is recommended to use either a condensing combinator (Ret1,RetM) or condensing compose e.g. [ComposeRet1] , [ComposeRetM]

Example
data := map[string][]int{
	"alpha": []int{1, 2},
	"beta":  []int{3},
	"gamma": []int{4, 5, 6},
	"delta": []int{7, 8},
}

//In this example we will fully specify the types of the optics
//This is is not necessary in normal usage.

//The left optic we will use in the compose
var leftOptic Optic[
	string,           //Index Type
	map[string][]int, //Source Type
	map[string][]int, //Result Type
	[]int,            //Focus type
	[]int,            //Result focus type
	ReturnMany,       //Return type
	ReadWrite,        //ReadWrite type
	UniDir,           //Dir type
	Pure,             //Error type
] = TraverseMap[string, []int]()

//This optic will recieve a map[string][]int and focus on the []int for each key
//Under modification it will allow the []int to be edited and combine the edits
//together into a map[string][]int.

//The right optic we will use in the compose
var rightOptic Optic[
	int,        //Index Type
	[]int,      //Source Type
	[]int,      //Result Type
	int,        //Focus type
	int,        //Result focus type
	ReturnMany, //Return type
	ReadWrite,  //ReadWrite type
	UniDir,     //Dir type
	Pure,       //Error type
] = TraverseSlice[int]()

//This optic will receive a []int] and focus on the individual ints.
//Under modification it will allow the ints to be edited
//and the result is a new []int with the new values.

var composedOptic Optic[
	lo.Tuple2[string, int],                  //Index Type
	map[string][]int,                        //Source Type
	map[string][]int,                        //Result Type
	int,                                     //Focus type
	int,                                     //Result focus type
	CompositionTree[ReturnMany, ReturnMany], //Return type
	CompositionTree[ReadWrite, ReadWrite],   //ReadWrite type
	CompositionTree[UniDir, UniDir],         //Dir type
	CompositionTree[Pure, Pure],             //Error type
] = ComposeBoth(leftOptic, rightOptic)

//The composed optic will receive a map[string][]int and focus on each individual int.
//Under modification it will allow the int to be edited
//and the result is map[string][]int with the updated values.

//Note the result index is a combination of the map string index and the slice int index.
//See ICompose for the ability to define a different index.

//MustIListOf retrieves the focuses and their indices and converts them to a slice
//The returned indices are the index of the map and the slice combines
var listOfResult []ValueI[lo.Tuple2[string, int], int] = MustGet(SliceOf(WithIndex(composedOptic), 8), data)
fmt.Println(listOfResult) //[{alpha 0}:1 {alpha 1}:2 {beta 0}:3 {delta 0}:7 {delta 1}:8 {gamma 0}:4 {gamma 1}:5 {gamma 2}:6]

//Over applies the custom function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the int value is multiplied by 100 only if the map key has a length > 4 and the slice index is even.
var overResult map[string][]int = MustModifyI(composedOptic, OpI(func(index lo.Tuple2[string, int], focus int) int {
	if len(index.A) > 4 && index.B%2 == 0 {
		return focus * 100
	}
	return focus
}), data)
fmt.Println(overResult) //map[alpha:[100 2] beta:[3] delta:[700 8] gamma:[400 5 600]]

//Index uses the composed index to lookup the element at
//data["gamma"][1]
//Through the use of IComposeBoth both of these lookups are
//performed efficiently.
indexResult, found := MustGetFirst(Index(composedOptic, lo.T2("gamma", 1)), data)
fmt.Println(indexResult, found) //5 true
Output:

[{alpha 0}:1 {alpha 1}:2 {beta 0}:3 {delta 0}:7 {delta 1}:8 {gamma 0}:4 {gamma 1}:5 {gamma 2}:6]
map[alpha:[100 2] beta:[3] delta:[700 8] gamma:[400 5 600]]
5 true

func ComposeI

func ComposeI[I, J, K, S, T, A, B, C, D any, RETI TReturnOne, RETL, RETR, RWI, RWL, RWR, DIRI, DIRL, DIRR, ERRL, ERRR any, ERRI TPure](ixmap IxMapper[I, J, K, RETI, RWI, DIRI, ERRI], o1 Optic[I, S, T, A, B, RETL, RWL, DIRL, ERRL], o2 Optic[J, A, B, C, D, RETR, RWR, DIRR, ERRR]) Optic[K, S, T, C, D, CompositionTree[RETL, RETR], CompositionTree[RWL, RWR], CompositionTree[DIRL, DIRR], CompositionTree[ERRL, ERRR]]

ComposeI returns an Optic composed of the 2 input optics using a custom combination of left and right indices in the result.

See:

  • Compose for a the general version that returns an optic using the right index.
  • ComposeLeft for a version that returns an optic using the left index.
  • ComposeBoth for a version that returns an optic using both indices combined together as a lo.Tuple2

If you are implementing a Combinator then it is recommended to use either a condensing combinator (Ret1,RetM) or condensing compose e.g. [ComposeRet1] , [ComposeRetM]

Example
//This example demonstrates the custom index mapping
//for an example on composition in general check the Compose function
data := [][]int{
	{1, 2, 3},
	{4, 5},
	{6, 7, 8},
}

//Combine the 2 indices into an array rather than the
//[lo.Tuple2] returned by IComposeBoth
ixMap := IxMap(func(left int, right int) [2]int {
	return [2]int{left, right}
})

//Note: the IxMap function does not support ReverseGet
//to recover the left and right indexes this will
//result in poor performance when using the Index() combinator.

//The composed optic focuses on the individual ints in the nested slices.
composedOptic := ComposeI(ixMap, TraverseSlice[[]int](), TraverseSlice[int]())

//Note that the index in the result is [2]int the result of our ixMap function
var listOfResult []ValueI[[2]int, int] = MustGet(SliceOf(WithIndex(composedOptic), 8), data)
fmt.Println(listOfResult) //[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]

//Over applies the custom function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the int value is multiplied by 100 only if both slice indices are even.
var overResult [][]int = MustModifyI(composedOptic, OpI(func(index [2]int, focus int) int {
	if index[0]%2 == 0 && index[1]%2 == 0 {
		return focus * 100
	}
	return focus
}), data)
fmt.Println(overResult) //[[100 2 300] [4 5] [600 7 800]]

//Index uses the composed index to lookup the element at
//data[1][1]
//Note: even though the IxMap has an inefficient implementation
//it still returns the correct results
//For an efficient implementation use IComposeBoth or implement a custom IxMapper
indexResult, found := MustGetFirst(Index(composedOptic, [2]int{1, 1}), data)
fmt.Println(indexResult, found) //5 true
Output:

[[0 0]:1 [0 1]:2 [0 2]:3 [1 0]:4 [1 1]:5 [2 0]:6 [2 1]:7 [2 2]:8]
[[100 2 300] [4 5] [600 7 800]]
5 true

func ComposeLeft

func ComposeLeft[I, J, S, T, A, B, C, D, RETI, RETJ, RWI, RWJ, DIRI, DIRJ, ERRI, ERRJ any](left Optic[I, S, T, A, B, RETI, RWI, DIRI, ERRI], right Optic[J, A, B, C, D, RETJ, RWJ, DIRJ, ERRJ]) Optic[I, S, T, C, D, CompositionTree[RETI, RETJ], CompositionTree[RWI, RWJ], CompositionTree[DIRI, DIRJ], CompositionTree[ERRI, ERRJ]]

ComposeLeft returns an Optic composed of the 2 input optics using the left index in the result.

See:

  • Compose for a the general version that returns an optic using the right index.
  • ComposeBoth for a version that returns an optic using both indices combined together.
  • ComposeI for a version that returns a custom index.

If you are implementing a Combinator then it is recommended to use either a condensing combinator (Ret1,RetM) or condensing compose e.g. [ComposeRet1] , [ComposeRetM]

Example
data := []lo.Tuple2[string, int]{
	lo.T2("alpha", 1),
	lo.T2("beta", 2),
	lo.T2("gamma", 3),
	lo.T2("delta", 4),
}

//In this example we will fully specify the types of the optics
//This is is not necessary in normal usage.

//The left optic we will use in the compose
var leftOptic Optic[
	int,                      //Index Type
	[]lo.Tuple2[string, int], //Source Type
	[]lo.Tuple2[string, int], //Result Type
	lo.Tuple2[string, int],   //Focus type
	lo.Tuple2[string, int],   //Result focus type
	ReturnMany,               //Return type
	ReadWrite,                //ReadWrite type
	UniDir,                   //Dir type
	Pure,                     //Error type
] = TraverseSlice[lo.Tuple2[string, int]]()

//This optic will receive a slice of tuples and focus on the individual tuples.
//Under modification it will allow the tuple to be edited and combine the edits
//together into a slice of tuples.

//The right optic we will use in the compose
var rightOptic Optic[
	int,                    //Index Type
	lo.Tuple2[string, int], //Source Type
	lo.Tuple2[string, int], //Result Type
	string,                 //Focus type
	string,                 //Result focus type
	ReturnOne,              //Return type
	ReadWrite,              //ReadWrite type
	UniDir,                 //Dir type
	Pure,                   //Error type
] = T2A[string, int]()

//This optic will receive a tuple and focus on the first element.
//Under modification it will allow the first element to be edited
//tand the result is a tuple with a modified first element.

var composedOptic Optic[
	int,                                    //Index Type
	[]lo.Tuple2[string, int],               //Source Type
	[]lo.Tuple2[string, int],               //Result Type
	string,                                 //Focus type
	string,                                 //Result focus type
	CompositionTree[ReturnMany, ReturnOne], //Return type
	CompositionTree[ReadWrite, ReadWrite],  //ReadWrite type
	CompositionTree[UniDir, UniDir],        //Dir type
	CompositionTree[Pure, Pure],            //Error type
] = ComposeLeft(leftOptic, rightOptic)

//The composed optic will receive a slice of tuples and focus on the first element of each tuple.
//Under modification it will allow the first element to be edited
//and the result is slice of tuples with a modified first element.

//Note the result index is the int index from the left optic
//See ICompose for the ability to define a different index.

//MustIListOf retrieves the focuses and their indices and converts them to a slice
//The returned indices are the index into the slice.
var listOfResult []ValueI[int, string] = MustGet(SliceOf(WithIndex(composedOptic), 4), data)
fmt.Println(listOfResult) //[0:alpha 1:beta 2:gamma 3:delta]

//Over applies the custom ToUpper function to each focused element and combines
//them into a new copy of the original data structure.
//In the result the first elements with an even index are in upper case the second elements are unmodified.
var overResult []lo.Tuple2[string, int] = MustModifyI(composedOptic, OpI(func(index int, focus string) string {
	if index%2 == 0 {
		return strings.ToUpper(focus)
	}
	return focus
}), data)
fmt.Println(overResult) //[{ALPHA 1} {beta 2} {GAMMA 3} {delta 3}]
Output:

[0:alpha 1:beta 2:gamma 3:delta]
[{ALPHA 1} {beta 2} {GAMMA 3} {delta 4}]

func Concat

func Concat[I, S, A any, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2 any](o1 Optic[I, S, S, A, A, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, S, A, A, RET2, RW2, DIR2, ERR2]) Optic[I, S, S, A, A, ReturnMany, CompositionTree[RW1, RW2], UniDir, CompositionTree[ERR1, ERR2]]
Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
}

data2 := map[string]int{
	"gamma": 3,
	"delta": 4,
}

res := MustGet(
	MapOfReduced(
		Concat(
			Compose(
				T2A[map[string]int, map[string]int](),
				TraverseMap[string, int](),
			),
			Compose(
				T2B[map[string]int, map[string]int](),
				TraverseMap[string, int](),
			),
		),
		FirstReducer[int](),
		len(data)+len(data2),
	),
	lo.T2(data, data2),
)

fmt.Println(res)
Output:

map[alpha:1 beta:2 delta:4 gamma:3]

func Concat3

func Concat3[I, S, A any, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2, RET3, RW3, DIR3, ERR3 any](o1 Optic[I, S, S, A, A, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, S, A, A, RET2, RW2, DIR2, ERR2], o3 Optic[I, S, S, A, A, RET3, RW3, DIR3, ERR3]) Optic[I, S, S, A, A, ReturnMany, CompositionTree[CompositionTree[RW1, RW2], RW3], UniDir, CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]

func Concat4

func Concat4[I, S, A any, RET1, RW1, DIR1, ERR1, RET2, RW2, DIR2, ERR2, RET3, RW3, DIR3, ERR3, RET4, RW4, DIR4, ERR4 any](o1 Optic[I, S, S, A, A, RET1, RW1, DIR1, ERR1], o2 Optic[I, S, S, A, A, RET2, RW2, DIR2, ERR2], o3 Optic[I, S, S, A, A, RET3, RW3, DIR3, ERR3], o4 Optic[I, S, S, A, A, RET4, RW4, DIR4, ERR4]) Optic[I, S, S, A, A, ReturnMany, CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], UniDir, CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]]]

func ConcatN

func ConcatN[I, S, A any, RET any, RW any, DIR any, ERR any](o ...Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[I, S, S, A, A, ReturnMany, RW, UniDir, ERR]

The ConcatN combinator returns all the focuses of the given optics in sequence.

func Const

func Const[S any, A any](v A) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]
Example
data := []int{1, 2, 3, 4, 5}

res := MustGet(
	SliceOf(
		Compose(
			TraverseSlice[int](),
			If(
				Even[int](),
				Const[int]("even"),
				Const[int]("odd"),
			),
		),
		len(data),
	),
	data,
)

fmt.Println(res)
Output:

[odd even odd even odd]

func ConstI

func ConstI[S, A any, I any, ERR TPure](i I, v A, ixMatch Predicate[lo.Tuple2[I, I], ERR]) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

ConstI returns an optic that focuses a constant index and value.

See:

  • Const for a non index aware version
Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
}

res := MustGet(
	MapOfReduced(
		Concat(
			TraverseMap[string, int](),
			ConstI[map[string]int]("delta", 4, EqT2[string]()),
		),
		FirstReducer[int](),
		len(data),
	),
	data,
)

fmt.Println(res)
Output:

map[alpha:1 beta:2 delta:4 gamma:3]

func ConstIP

func ConstIP[S, T, A, B any, I any, ERR TPure](i I, v A, ixMatch Predicate[lo.Tuple2[I, I], ERR]) Optic[I, S, T, A, B, ReturnOne, ReadOnly, UniDir, Pure]

func ConstP

func ConstP[S, T, A, B any](v A) Optic[Void, S, T, A, B, ReturnOne, ReadOnly, UniDir, Pure]

func Contains

func Contains[I, S, T any, A comparable, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], val ...A) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

Contains returns a Predicate that is satisfied if any focus satisfies the passed predicate.

Note: If the optic focuses no elements then Contains returns false.

See: - In for a simple predicate version. - All for a version that requires all focuses to satisfy he predicate

Example
data := []string{"1", "2", "3", "4"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result bool
var err error
result, err = Get(Contains(optic, "3"), data)
fmt.Println(result, err)
Output:

true <nil>

func DelveT2

func DelveT2[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple2[I, I], lo.Tuple2[S, S], lo.Tuple2[S, S], lo.Tuple2[A, A], lo.Tuple2[A, A], RET, RW, UniDir, ERR]

The DelveT2 combinator focuses each element of a lo.Tuple2 using the given Optic

func DelveT3

func DelveT3[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple3[I, I, I], lo.Tuple3[S, S, S], lo.Tuple3[S, S, S], lo.Tuple3[A, A, A], lo.Tuple3[A, A, A], RET, RW, UniDir, ERR]

The DelveT3 combinator focuses each element of a lo.Tuple3 using the given Optic

func DelveT4

func DelveT4[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple4[I, I, I, I], lo.Tuple4[S, S, S, S], lo.Tuple4[S, S, S, S], lo.Tuple4[A, A, A, A], lo.Tuple4[A, A, A, A], RET, RW, UniDir, ERR]

The DelveT4 combinator focuses each element of a lo.Tuple4 using the given Optic

func DelveT5

func DelveT5[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple5[I, I, I, I, I], lo.Tuple5[S, S, S, S, S], lo.Tuple5[S, S, S, S, S], lo.Tuple5[A, A, A, A, A], lo.Tuple5[A, A, A, A, A], RET, RW, UniDir, ERR]

The DelveT5 combinator focuses each element of a lo.Tuple5 using the given Optic

func DelveT6

func DelveT6[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple6[I, I, I, I, I, I], lo.Tuple6[S, S, S, S, S, S], lo.Tuple6[S, S, S, S, S, S], lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[A, A, A, A, A, A], RET, RW, UniDir, ERR]

The DelveT6 combinator focuses each element of a lo.Tuple6 using the given Optic

func DelveT7

func DelveT7[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple7[I, I, I, I, I, I, I], lo.Tuple7[S, S, S, S, S, S, S], lo.Tuple7[S, S, S, S, S, S, S], lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[A, A, A, A, A, A, A], RET, RW, UniDir, ERR]

The DelveT7 combinator focuses each element of a lo.Tuple7 using the given Optic

func DelveT8

func DelveT8[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple8[I, I, I, I, I, I, I, I], lo.Tuple8[S, S, S, S, S, S, S, S], lo.Tuple8[S, S, S, S, S, S, S, S], lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[A, A, A, A, A, A, A, A], RET, RW, UniDir, ERR]

The DelveT8 combinator focuses each element of a lo.Tuple8 using the given Optic

func DelveT9

func DelveT9[I any, S any, A any, RET any, RW any, DIR any, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR]) Optic[lo.Tuple9[I, I, I, I, I, I, I, I, I], lo.Tuple9[S, S, S, S, S, S, S, S, S], lo.Tuple9[S, S, S, S, S, S, S, S, S], lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[A, A, A, A, A, A, A, A, A], RET, RW, UniDir, ERR]

The DelveT9 combinator focuses each element of a lo.Tuple9 using the given Optic

func Desc

func Desc[A, ERR any](lessPred OrderByPredicate[A, ERR]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

The Desc combinator converts am OrderByOperation to operate in the reverse order.

See:

  • DescI for an index aware version.
Example
data := []int{1, 10, 2, 9, 3, 8, 4, 7, 5, 6}

optic := Ordered(
	TraverseSlice[int](),
	Desc(
		OrderBy(
			Identity[int](),
		),
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[10 9 8 7 6 5 4 3 2 1]

func DescI

func DescI[I, A, ERR any](less OrderByPredicateI[I, A, ERR]) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

The DescI combinator converts an OrderByPredicateI to operate in the reverse order.

See:

  • Desc for a non index aware version.
Example
data := map[int]string{
	4: "alpha",
	3: "beta",
	2: "gamma",
	1: "delta",
}

optic := OrderedI(
	TraverseMap[int, string](),
	DescI(
		OrderByI(
			ValueIIndex[int, string](),
		),
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[alpha beta gamma delta]

func DiffCol

func DiffCol[I, A any, RET TReturnOne, ERR any, ERRI TPure](
	right Collection[I, A, ERR],
	threshold float64,
	distance Operation[lo.Tuple2[A, A], float64, RET, ERR],
	ixMatch Predicate[lo.Tuple2[I, I], ERRI],
	filterDiffType DiffType,
	detectPosChange bool,
) Optic[Diff[I, A], Collection[I, A, ERR], Collection[I, A, ERR], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]
Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("Alpha", "gamma", "beta", "epsilon")

optic := DiffCol[int](
	before,
	2,
	EPure(EditDistance(TraverseString(), EditLevenshtein, EqT2[rune](), 4)),
	EqT2[int](),
	DiffNone,
	true,
)

for i, v := range MustGet(SeqIOf(optic), after) {
	fmt.Println(i, "After Value", v)
}
Output:

DiffModify(Pos=0->0,Index=0->0,BeforeValue=alpha,Dist=1) After Value {true Alpha}
DiffModify(Pos=2->1,Index=2->1,BeforeValue=gamma,Dist=0) After Value {true gamma}
DiffModify(Pos=1->2,Index=1->2,BeforeValue=beta,Dist=0) After Value {true beta}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true epsilon}

func DiffColI

func DiffColI[I, A any, RET TReturnOne, ERR any, ERRI TPure](
	right Collection[I, A, ERR],
	threshold float64,
	distance Operation[lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, RET, ERR],
	ixMatch Predicate[lo.Tuple2[I, I], ERRI],
	filterDiffType DiffType,
	detectPosChange bool,
) Optic[Diff[I, A], Collection[I, A, ERR], Collection[I, A, ERR], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

func DiffColT2

func DiffColT2[I, A any, RET TReturnOne, ERR any, ERRI TPure](threshold float64, distance Operation[lo.Tuple2[A, A], float64, RET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRI], filterDiffType DiffType, detectPosChange bool) Optic[Diff[I, A], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffColT2 returns an Traversal that focuses on the differences between 2 Collection. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Collection in the first position and the reference Collection in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • [DiffColE] for an impure version
  • DiffColT2I for an index aware version
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.
Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("Alpha", "gamma", "beta", "epsilon")

optic := DiffColT2[int](2, EPure(EditDistance(TraverseString(), EditLevenshtein, EqT2[rune](), 4)), EqT2[int](), DiffNone, true)

for i, v := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(i, "After Value", v)
}
Output:

DiffModify(Pos=0->0,Index=0->0,BeforeValue=alpha,Dist=1) After Value {true Alpha}
DiffModify(Pos=2->1,Index=2->1,BeforeValue=gamma,Dist=0) After Value {true gamma}
DiffModify(Pos=1->2,Index=1->2,BeforeValue=beta,Dist=0) After Value {true beta}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true epsilon}

func DiffColT2I

func DiffColT2I[I, A any, RET TReturnOne, ERR any, ERRI TPure](
	threshold float64,
	distance Operation[lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, RET, ERR],
	ixMatch Predicate[lo.Tuple2[I, I], ERRI],
	filterDiffType DiffType,
	detectPosChange bool,
) Optic[Diff[I, A], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffColT2I returns an Traversal that focuses on the differences between 2 [Collection]s. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Collection in the first position and the reference Collection in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffColT2 for a non index aware version
  • Diff for the index detailing the detected diff.
  • DistanceI for a convenience constructor for the distance operation.
Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("gamma", "Alpha", "epsilon", "alpha")

optic := DiffColT2I[int](
	2,
	DistanceI(func(indexA int, a string, indexB int, b string) float64 {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA-lenB)) + math.Abs(float64(indexA-indexB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist
	}),
	EqT2[int](),
	DiffNone,
	true,
)

for diffType, value := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(diffType, "After Value", value)
}
Output:

DiffModify(Pos=2->0,Index=2->0,BeforeValue=gamma,Dist=2) After Value {true gamma}
DiffRemove(Index=1,Value=beta) After Value {false }
DiffModify(Pos=0->1,Index=0->1,BeforeValue=alpha,Dist=2) After Value {true Alpha}
DiffAdd(Index=2) After Value {true epsilon}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true alpha}

func DiffColType

func DiffColType[I, S, A any, RET TReturnOne, ERR any](s CollectionType[I, S, S, A, A, ERR], right S, threshold float64, distance Operation[lo.Tuple2[A, A], float64, RET, ERR], filterDiff DiffType) Optic[Diff[I, A], S, S, mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

func DiffColTypeI

func DiffColTypeI[I, S, A any, RET TReturnOne, ERR any](s CollectionType[I, S, S, A, A, ERR], right S, threshold float64, distance Operation[lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[I, A], S, S, mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

func DiffColTypeT2

func DiffColTypeT2[I, S, A any, RET TReturnOne, ERR any](s CollectionType[I, S, S, A, A, ERR], threshold float64, distance Operation[lo.Tuple2[A, A], float64, RET, ERR], filterDiff DiffType) Optic[Diff[I, A], lo.Tuple2[S, S], lo.Tuple2[S, S], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffColTypeT2 returns a Traversal that focuses on the differences between 2 [CollectionTypes]. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Collection in the first position and the reference Collection in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • [DiffColTypeE] for an impure version
  • DiffColTypeT2I for an index aware version
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.
Example
diff := Compose(
	AsModify(
		TraverseT2P[int, float64](),
		UpCast[int, float64](),
	),
	SubT2[float64](),
)

sliceDiff := DiffColTypeT2(
	SliceColType[int](),
	1,
	EPure(diff),
	DiffNone,
)

result := MustGet(
	SliceOf(WithIndex(sliceDiff), 5),
	lo.T2(
		[]int{10, 20, 30},
		[]int{10, 21},
	),
)
fmt.Println(result)
Output:

[DiffModify(Pos=1->1,Index=1->1,BeforeValue=21,Dist=1):{true 20} DiffAdd(Index=2):{true 30}]

func DiffColTypeT2I

func DiffColTypeT2I[I, S, A any, RET TReturnOne, ERR any](s CollectionType[I, S, S, A, A, ERR], threshold float64, distance Operation[lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[I, A], lo.Tuple2[S, S], lo.Tuple2[S, S], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffColTypeT2I returns an Traversal that focuses on the differences between 2 [CollectionTypes]s. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Collection in the first position and the reference Collection in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffColTypeT2 for a non index aware version
  • Diff for the index detailing the detected diff.
  • DistanceI for a convenience constructor for the distance operation.
Example
before := []string{"alpha", "beta", "gamma", "delta"}
after := []string{"gamma", "Alpha", "epsilon", "alpha"}

optic := DiffColTypeT2I[int](
	SliceColType[string](),
	2,
	DistanceI(func(indexA int, a string, indexB int, b string) float64 {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA-lenB)) + math.Abs(float64(indexA-indexB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist
	}),
	DiffNone,
)

for diffType, value := range MustGet(SeqIOf(optic), lo.T2(after, before)) {

	fmt.Println(diffType, "After Value", value)
}
Output:

DiffModify(Pos=2->0,Index=2->0,BeforeValue=gamma,Dist=2) After Value {true gamma}
DiffRemove(Index=1,Value=beta) After Value {false }
DiffModify(Pos=0->1,Index=0->1,BeforeValue=alpha,Dist=2) After Value {true Alpha}
DiffAdd(Index=2) After Value {true epsilon}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true alpha}

func DiffMap

func DiffMap[K comparable, S any, RET TReturnOne, ERR any](col map[K]S, threshold float64, distance Operation[lo.Tuple2[S, S], float64, RET, ERR], filterDiff DiffType) Optic[Diff[K, S], map[K]S, map[K]S, mo.Option[S], mo.Option[S], ReturnMany, ReadWrite, UniDir, ERR]

DiffMap returns a Traversal that focuses on the differences between the given and focused Maps. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffMapI for an index aware version
  • DiffMapT2I for a version that compares 2 focused Maps.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffMapI

func DiffMapI[K comparable, S any, RET TReturnOne, ERR any](col map[K]S, threshold float64, distance Operation[lo.Tuple2[ValueI[K, S], ValueI[K, S]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[K, S], map[K]S, map[K]S, mo.Option[S], mo.Option[S], ReturnMany, ReadWrite, UniDir, ERR]

DiffMapI returns a Traversal that focuses on the differences between a given and focused Map. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffMap for a non index aware version
  • DiffMapT2 for a version that compares 2 focused Maps.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffMapT2

func DiffMapT2[K comparable, S any, RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[S, S], float64, RET, ERR], filterDiff DiffType) Optic[Diff[K, S], lo.Tuple2[map[K]S, map[K]S], lo.Tuple2[map[K]S, map[K]S], mo.Option[S], mo.Option[S], ReturnMany, ReadWrite, UniDir, ERR]

DiffMapT2 returns a Traversal that focuses on the differences between 2 Maps. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Map in the first position and the reference Map in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffMapT2I for an index aware version
  • DiffMap for a a version that compares against a given Map
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffMapT2I

func DiffMapT2I[K comparable, S any, RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[ValueI[K, S], ValueI[K, S]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[K, S], lo.Tuple2[map[K]S, map[K]S], lo.Tuple2[map[K]S, map[K]S], mo.Option[S], mo.Option[S], ReturnMany, ReadWrite, UniDir, ERR]

DiffMapT2I returns a Traversal that focuses on the differences between 2 Maps. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Map in the first position and the reference Map in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffMapT2 for a non index aware version
  • DiffMapI for a a version that compares against a given Map
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffSlice

func DiffSlice[A any, RET TReturnOne, ERR any](col []A, threshold float64, distance Operation[lo.Tuple2[A, A], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, A], []A, []A, mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffSlice returns a Traversal that focuses on the differences between the given and focused Slices. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffSliceI for an index aware version
  • DiffSliceT2I for a version that compares 2 focused Slices.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffSliceI

func DiffSliceI[A any, RET TReturnOne, ERR any](col []A, threshold float64, distance Operation[lo.Tuple2[ValueI[int, A], ValueI[int, A]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, A], []A, []A, mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffSliceI returns a Traversal that focuses on the differences between a given and focused Slice. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffSlice for a non index aware version
  • DiffSliceT2 for a version that compares 2 focused Slices.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffSliceT2

func DiffSliceT2[A any, RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[A, A], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, A], lo.Tuple2[[]A, []A], lo.Tuple2[[]A, []A], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffSliceT2 returns a Traversal that focuses on the differences between 2 Slices. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Slice in the first position and the reference Slice in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffSliceT2I for an index aware version
  • DiffSlice for a a version that compares against a given Slice
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffSliceT2I

func DiffSliceT2I[A any, RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[ValueI[int, A], ValueI[int, A]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, A], lo.Tuple2[[]A, []A], lo.Tuple2[[]A, []A], mo.Option[A], mo.Option[A], ReturnMany, ReadWrite, UniDir, ERR]

DiffSliceT2I returns a Traversal that focuses on the differences between 2 Slices. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified Slice in the first position and the reference Slice in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffSliceT2 for a non index aware version
  • DiffSliceI for a a version that compares against a given Slice
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffString

func DiffString[RET TReturnOne, ERR any](col string, threshold float64, distance Operation[lo.Tuple2[rune, rune], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, rune], string, string, mo.Option[rune], mo.Option[rune], ReturnMany, ReadWrite, UniDir, ERR]

DiffString returns a Traversal that focuses on the differences between the given and focused Strings. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffStringI for an index aware version
  • DiffStringT2I for a version that compares 2 focused Strings.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffStringI

func DiffStringI[RET TReturnOne, ERR any](col string, threshold float64, distance Operation[lo.Tuple2[ValueI[int, rune], ValueI[int, rune]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, rune], string, string, mo.Option[rune], mo.Option[rune], ReturnMany, ReadWrite, UniDir, ERR]

DiffStringI returns a Traversal that focuses on the differences between a given and focused String. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffString for a non index aware version
  • DiffStringT2 for a version that compares 2 focused Strings.
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffStringT2

func DiffStringT2[RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[rune, rune], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, rune], lo.Tuple2[string, string], lo.Tuple2[string, string], mo.Option[rune], mo.Option[rune], ReturnMany, ReadWrite, UniDir, ERR]

DiffStringT2 returns a Traversal that focuses on the differences between 2 Strings. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified String in the first position and the reference String in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffStringT2I for an index aware version
  • DiffString for a a version that compares against a given String
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DiffStringT2I

func DiffStringT2I[RET TReturnOne, ERR any](threshold float64, distance Operation[lo.Tuple2[ValueI[int, rune], ValueI[int, rune]], float64, RET, ERR], filterDiff DiffType) Optic[Diff[int, rune], lo.Tuple2[string, string], lo.Tuple2[string, string], mo.Option[rune], mo.Option[rune], ReturnMany, ReadWrite, UniDir, ERR]

DiffStringT2I returns a Traversal that focuses on the differences between 2 Strings. The distance Operation is used to determine if an element has either changed position or been modified. Elements are considered same if they have the smallest distance compared to all other elements and the distance is lower than the threshold.

Note: The source tuple should have the modified String in the first position and the reference String in the second position. This is compatible with [T2Dup] returning the modified tree.

Details of the diff are encoded in the index of the focused elements.

See:

  • DiffStringT2 for a non index aware version
  • DiffStringI for a a version that compares against a given String
  • Diff for the index detailing the detected diff.
  • Distance for a convenience constructor for the distance operation.

func DirL

func DirL[I, S, T, A, B any, RET any, RW any, DIRL any, DIRR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIRL, DIRR], ERR]) Optic[I, S, T, A, B, RET, RW, DIRL, ERR]

The DirL re-constrain converts an Optic's direction type to the left side of the CompositionTree where the right side is BiDir.

CompositionTree[DIRL any, DIRR TBiDir] --> DIRL

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticBd Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir], //Note the BiDir on the left
	CompositionTree[Pure, Pure],
] = Compose(
	Mul(10),
	Add(3),
)

var reconstrainedBd Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir, //DirL reconstrained to BiDir
	Pure,
] = Ret1(Rw(DirL(EPure(opticBd))))

fmt.Println(reconstrainedBd.OpticType())

var opticUd Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadOnly, ReadWrite],
	CompositionTree[UniDir, BiDir], //Note the UniDir on the right
	CompositionTree[Pure, Pure],
] = Compose(
	Mod(10),
	Mul(2),
)

var reconstrainedUd Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadOnly,
	UniDir, //DirL reconstrained to BiDir
	Pure,
] = Ret1(Ro(DirL(EPure(opticUd))))

fmt.Println(reconstrainedUd.OpticType())
Output:

Iso
Getter

func DirMerge

func DirMerge[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR, DIR], ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The DirMerge re-constrain combines identical left and right side direction types of a composition tree..

CompositionTree[DIR, DIR] --> DIR

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirMergeL

func DirMergeL[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR1], DIR2], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, DIR2], ERR]

The DirMergeL re-constrain combines identical left and right side of the left side of a nested {CompositionTree]

CompositionTree[CompositionTree[DIR1, DIR1], DIR2] --> CompositionTree[DIR1, DIR2]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirMergeR

func DirMergeR[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, CompositionTree[DIR2, DIR2]], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, DIR2], ERR]

The DirMergeR re-constrain combines identical left and right side of the right side of a nested {CompositionTree]

CompositionTree[DIR1, CompositionTree[DIR2, DIR2]] --> CompositionTree[DIR1, DIR2]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirR

func DirR[I, S, T, A, B any, RET any, RW any, DIRL TBiDir, DIRR any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIRL, DIRR], ERR]) Optic[I, S, T, A, B, RET, RW, DIRR, ERR]

The DirR re-constrain converts an Optic's direction type to the right side of the CompositionTree where the left side is BiDir.

CompositionTree[DIRL TBiDir, DIRR any] --> DIRR

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticUd Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadOnly],
	CompositionTree[BiDir, UniDir], //Note the ReadOnly on the right
	CompositionTree[Pure, Pure],
] = Compose(
	Mul(10),
	Mod(3),
)

var reconstrainedUd Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadOnly,
	UniDir, //BdR reconstrained to UniDir
	Pure,
] = Ret1(Ro(DirR(EPure(opticUd))))

fmt.Println(reconstrainedUd.OpticType())

var opticBd Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir], //Note the BiDir on the right
	CompositionTree[Pure, Pure],
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrainedBd Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir, //BdR reconstrained to BiDir
	Pure,
] = Ret1(Rw(DirR(EPure(opticBd))))

fmt.Println(reconstrainedBd.OpticType())
Output:

Getter
Iso

func DirSwap

func DirSwap[I, S, T, A, B any, RET any, RW any, DIRL any, DIRR any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIRL, DIRR], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[DIRR, DIRL], ERR]

The DirSwap re-constrain swaps the left and right side of an Optic's direction type CompositionTree.

CompositionTree[DIRL, DIRR] --> CompositionTree[DIRR, DIRL]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirSwapL

func DirSwapL[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, DIR3 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR2], DIR3], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR2, DIR1], DIR3], ERR]

The DirSwapL re-constrain swaps the left and right side of the left side of a nested CompositionTree.

CompositionTree[CompositionTree[DIR1, DIR2], DIR3] --> CompositionTree[CompositionTree[DIR2, DIR1], DIR3]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirSwapR

func DirSwapR[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, DIR3 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, CompositionTree[DIR2, DIR3]], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, CompositionTree[DIR3, DIR3]], ERR]

The DirSwapR re-constrain swaps the left and right side of the right side of a nested CompositionTree.

CompositionTree[DIR1, CompositionTree[DIR2, DIR3]] --> CompositionTree[DIR1, CompositionTree[DIR3, DIR2]]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirTrans

func DirTrans[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, DIR3 any, DIR4 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR2], CompositionTree[DIR3, DIR4]], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR3], CompositionTree[DIR2, DIR4]], ERR]

The DirTrans re-constrain transposes the middle direction type of a nested CompositionTree.

CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4] --> CompositionTree[CompositionTree[ERR1, ERR3], CompositionTree[ERR2, ERR4]

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirTransL

func DirTransL[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, DIR3 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR2], DIR3], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[CompositionTree[DIR1, DIR3], DIR2], ERR]

The DirTransL re-constrain transposes the right element with the right child of a nested composition tree to the left.

CompositionTree[CompositionTree[DIR1, DIR2], DIR3] --> CompositionTree[CompositionTree[DIR1, DIR3], DIR2] This has the effect of removing a level of nested from the DIR2 path of the composition tree.

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func DirTransR

func DirTransR[I, S, T, A, B any, RET any, RW any, DIR1 any, DIR2 any, DIR3 any, ERR any](o Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR1, CompositionTree[DIR2, DIR3]], ERR]) Optic[I, S, T, A, B, RET, RW, CompositionTree[DIR2, CompositionTree[DIR1, DIR3]], ERR]

The DirTransR re-constrain transposes the left element with the left child of a nested composition tree to the right.

CompositionTree[DIR1, CompositionTree[DIR2, DIR3]] --> CompositionTree[DIR2, CompositionTree[DIR1, DIR3]] This has the effect of removing a level of nested from the DIR2 path of the composition tree.

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func Distance

func Distance[A any](fnc func(a, b A) float64) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], float64, float64, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for a distance Operation for use with DiffCol

The function should return the edit distance between a and b See:

Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("Alpha", "gamma", "beta", "epsilon")

optic := DiffColT2[int](
	2,
	Distance(func(a, b string) float64 {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA - lenB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist
	}),
	EqT2[int](),
	DiffNone,
	true,
)

for i, v := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(i, "After Value", v)
}
Output:

DiffModify(Pos=0->0,Index=0->0,BeforeValue=alpha,Dist=1) After Value {true Alpha}
DiffModify(Pos=2->1,Index=2->1,BeforeValue=gamma,Dist=0) After Value {true gamma}
DiffModify(Pos=1->2,Index=1->2,BeforeValue=beta,Dist=0) After Value {true beta}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true epsilon}

func DistanceE

func DistanceE[I, A any](fnc func(ctx context.Context, a A, b A) (float64, error)) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], float64, float64, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an index aware distance Operation for use with DiffColI

The function should return the edit distance between a and b See:

Example
before := ColErr(ValCol(
	"alpha",
	"beta",
	"gamma",
	"delta",
))
after := ColErr(ValCol(
	"Alpha",
	"gamma",
	"beta",
	"epsilon",
))

optic := DiffColT2[int](
	2,
	DistanceE[int](func(ctx context.Context, a, b string) (float64, error) {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA - lenB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist, nil
	}),
	EqT2[int](),
	DiffNone,
	true,
)

seq, err := Get(SeqIEOf(optic), lo.T2(after, before))
if err != nil {
	log.Fatal(err)
}
for val := range seq {
	i, v, err := val.Get()
	fmt.Println(i, "After Value", v, "Err:", err)
}
Output:

DiffModify(Pos=0->0,Index=0->0,BeforeValue=alpha,Dist=1) After Value {true Alpha} Err: <nil>
DiffModify(Pos=2->1,Index=2->1,BeforeValue=gamma,Dist=0) After Value {true gamma} Err: <nil>
DiffModify(Pos=1->2,Index=1->2,BeforeValue=beta,Dist=0) After Value {true beta} Err: <nil>
DiffRemove(Index=3,Value=delta) After Value {false } Err: <nil>
DiffAdd(Index=3) After Value {true epsilon} Err: <nil>

func DistanceI

func DistanceI[I, A any](fnc func(ia I, a A, ib I, b A) float64) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, float64, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an index aware distance Operation for use with DiffColI

The function should return the edit distance between a and b See:

Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("gamma", "Alpha", "epsilon", "alpha")

optic := DiffColT2I[int](
	2,
	DistanceI(func(indexA int, a string, indexB int, b string) float64 {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA-lenB)) + math.Abs(float64(indexA-indexB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist
	}),
	EqT2[int](),
	DiffNone,
	true,
)

for i, v := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(i, "After Value", v)
}
Output:

DiffModify(Pos=2->0,Index=2->0,BeforeValue=gamma,Dist=2) After Value {true gamma}
DiffRemove(Index=1,Value=beta) After Value {false }
DiffModify(Pos=0->1,Index=0->1,BeforeValue=alpha,Dist=2) After Value {true Alpha}
DiffAdd(Index=2) After Value {true epsilon}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true alpha}

func DistanceIE

func DistanceIE[I, A any](fnc func(ctx context.Context, ia I, a A, ib I, b A) (float64, error)) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], float64, float64, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an index aware distance Operation for use with DiffColI

The function should return the edit distance between a and b See:

Example
before := ColErr(ValCol("alpha", "beta", "gamma", "delta"))
after := ColErr(ValCol("gamma", "Alpha", "epsilon", "alpha"))

optic := DiffColT2I[int](
	2,
	DistanceIE(func(ctx context.Context, indexA int, a string, indexB int, b string) (float64, error) {
		lenA := len(a)
		lenB := len(b)

		dist := math.Abs(float64(lenA-lenB)) + math.Abs(float64(indexA-indexB))

		minLen := min(lenA, lenB)
		for i := 0; i < minLen; i++ {
			if a[i] != b[i] {
				dist = dist + 1
			}
		}

		return dist, nil
	}),
	EqT2[int](),
	DiffNone,
	true,
)

seq, err := Get(SeqIEOf(optic), lo.T2(after, before))
if err != nil {
	log.Fatal(err)
}
for val := range seq {
	i, v, err := val.Get()
	fmt.Println(i, "After Value", v, "Err:", err)
}
Output:

DiffModify(Pos=2->0,Index=2->0,BeforeValue=gamma,Dist=2) After Value {true gamma} Err: <nil>
DiffRemove(Index=1,Value=beta) After Value {false } Err: <nil>
DiffModify(Pos=0->1,Index=0->1,BeforeValue=alpha,Dist=2) After Value {true Alpha} Err: <nil>
DiffAdd(Index=2) After Value {true epsilon} Err: <nil>
DiffRemove(Index=3,Value=delta) After Value {false } Err: <nil>
DiffAdd(Index=3) After Value {true alpha} Err: <nil>

func DistancePercent

func DistancePercent[I, J, S, T, T2, B, C any, RETO, RETL TReturnOne, RWO, RWL any, DIRO, DIRL any, ERRO, ERRL TPure](distance Optic[I, lo.Tuple2[S, S], T, float64, B, RETO, RWO, DIRO, ERRO], length Optic[J, S, T2, int, C, RETL, RWL, DIRL, ERRL]) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], float64, float64, ReturnOne, ReadOnly, UniDir, Pure]

The DistancePercent combinator returns a modified distance optice that scales the returned value by the result of length.

Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("Alpha", "gamma", "beta", "epsilon")

optic := DiffColT2[int](
	0.5,
	DistancePercent(
		EditDistance(TraverseString(), EditLevenshtein, EqT2[rune](), 4),
		Length(TraverseString()),
	),
	EqT2[int](),
	DiffNone,
	true,
)

for i, v := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(i, "After Value", v)
}
Output:

DiffModify(Pos=0->0,Index=0->0,BeforeValue=alpha,Dist=0.2) After Value {true Alpha}
DiffModify(Pos=2->1,Index=2->1,BeforeValue=gamma,Dist=0) After Value {true gamma}
DiffModify(Pos=1->2,Index=1->2,BeforeValue=beta,Dist=0) After Value {true beta}
DiffRemove(Index=3,Value=delta) After Value {false }
DiffAdd(Index=3) After Value {true epsilon}

func DistancePercentI

func DistancePercentI[I, J, K, S, T, T2, B, C any, RETO, RETL TReturnOne, RWO, RWL any, DIRO, DIRL any, ERRO, ERRL any](distance Optic[K, lo.Tuple2[ValueI[I, S], ValueI[I, S]], T, float64, B, RETO, RWO, DIRO, ERRO], length Optic[J, S, T2, int, C, RETL, RWL, DIRL, ERRL]) Optic[Void, lo.Tuple2[ValueI[I, S], ValueI[I, S]], lo.Tuple2[ValueI[I, S], ValueI[I, S]], float64, float64, ReturnOne, ReadOnly, UniDir, CompositionTree[ERRO, ERRL]]

The DistancePercent combinator returns a modified distance optic that scales the returned value by the result of length.

Example
before := ValCol("alpha", "beta", "gamma", "delta")
after := ValCol("gamma", "Alpha", "epsilon", "alpha")

optic := DiffColT2I[int](
	0.5,
	EPure(DistancePercentI(
		AddOp(
			Compose(
				DelveT2(ValueIValue[int, string]()),
				EditDistance(TraverseString(), EditLevenshtein, EqT2[rune](), 4),
			),
			Compose4(
				DelveT2(ValueIIndex[int, string]()),
				SubT2[int](),
				Abs[int](),
				IsoCast[int, float64](),
			),
		),
		Compose(Length(TraverseString()), Mul(2)),
	)),
	EqT2[int](),
	DiffNone,
	true,
)

for index, val := range MustGet(SeqIOf(optic), lo.T2(after, before)) {
	fmt.Println(index, "After Value", val)
}
Output:

DiffModify(Pos=2->0,Index=2->0,BeforeValue=gamma,Dist=0.2) After Value {true gamma}
DiffRemove(Index=1,Value=beta) After Value {false }
DiffModify(Pos=0->1,Index=0->1,BeforeValue=alpha,Dist=0.2) After Value {true Alpha}
DiffAdd(Index=2) After Value {true epsilon}
DiffModify(Pos=3->3,Index=3->3,BeforeValue=delta,Dist=0.4) After Value {true alpha}

func Div

func Div[A Arithmetic](divisor A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Div returns an Iso that divides by a constant value.

See:

  • DivQuotient for a version that uses a constant quotient.
  • DivOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 10),
	lo.T2("b", 20),
	lo.T2("c", 30),
	lo.T2("d", 40),
	lo.T2("e", 50),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Divide each focused int by 10.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Div(10), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition Divides by 10 then adds 1
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Div(10), Add(10)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a divided by 10 context
//But when the result is built the value is multiplied by 10 again to return it to the original context
//In effect the Add(10) is in effect an Add(100)
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Div(10)), Add(10), data)
fmt.Println(preComposedResult)
Output:

[{a 1} {b 2} {c 3} {d 4} {e 5}]
[{a 11} {b 12} {c 13} {d 14} {e 15}]
[{a 110} {b 120} {c 130} {d 140} {e 150}]

func DivOp

func DivOp[S any, A Arithmetic, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

DivOp returns an Operation expression that multiplies the focuses of 2 [Operation]s.

See:

Example
data := []lo.Tuple2[int, int]{
	lo.T2(10, 6),
	lo.T2(20, 7),
	lo.T2(30, 8),
	lo.T2(40, 9),
	lo.T2(50, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Div function to the focuses of both optics
divider := DivOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(divider, lo.T2(20, 10))
fmt.Println(singleValueResult) // 2

//The created getter is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), divider, data)
fmt.Println(overResult) // [1 2 3 4 5]
Output:

2
[1 2 3 4 5]

func DivQuotient

func DivQuotient[A Arithmetic](quotient A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

DivQuotient returns an Iso that divides the given quotient by the focused value..

See:

  • Div for a version that uses a constant divisor.
  • DivOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 10),
	lo.T2("b", 20),
	lo.T2("c", 30),
	lo.T2("d", 40),
	lo.T2("e", 50),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Divide 100 by each focused int.
var modifyResult []lo.Tuple2[string, int] = MustModify(optic, DivQuotient(200), data)
fmt.Println(modifyResult)

//Getters are optics and can be composed.
//This composition Divides by 10 then adds 1
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(DivQuotient(200), Add(10)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a divided by 10 context
//But when the result is built the value is multiplied by 10 again to return it to the original context
//In effect the Add(10) is in effect an Add(100)
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Div(10)), Add(10), data)
fmt.Println(preComposedResult)
Output:

[{a 20} {b 10} {c 6} {d 5} {e 4}]
[{a 30} {b 20} {c 16} {d 15} {e 14}]
[{a 110} {b 120} {c 130} {d 140} {e 150}]

func DivT2

func DivT2[A Arithmetic]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

DivT2 returns an BinaryOp that divides 2 values.

See:

  • Div for a unary version.
  • DivOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []int{5, 2}

//returns a reducer that divides 100 sequentially by all the numbers in a slice
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(100, DivT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

10 true

func DownCast

func DownCast[S, A any]() Optic[Void, S, S, A, A, ReturnMany, ReadWrite, BiDir, Pure]

DownCast returns a Prism that performs a safe down cast from S to A and an upcast from A to S The down cast may fail in which case no result is focused. Warning: If the up cast fails a panic will occur.

See:

  • DownCastP for a polymorphic version
  • UpCast for a read only pure version.
  • IsoCast for a pure isomorphic version.
  • IsoCastE for isomorphic version that returns an error on cast failure.
Example
data := []any{1, 2, 3}

intCast := Compose(TraverseSlice[any](), DownCast[any, int]())

var res []int = MustGet(SliceOf(intCast, 3), data)
fmt.Println(res)

badData := []any{1, "two", 3}

res = MustGet(SliceOf(intCast, 3), badData)
fmt.Println(res)

var modifyResult []any = MustModify(intCast, Mul(2), data)
fmt.Println(modifyResult)

modifyResult = MustModify(intCast, Mul(2), badData)
fmt.Println(modifyResult)
Output:

[1 2 3]
[1 3]
[2 4 6]
[2 two 6]

func DownCastP

func DownCastP[S, A, B any]() Optic[Void, S, S, A, B, ReturnMany, ReadWrite, BiDir, Pure]

DownCastP returns a polymorphic Prism that performs a safe down cast from S to A and an upcast from B to S The down cast may fail in which case no result is focused. Warning: If the up cast fails a panic will occur.

See:

  • DownCast for a non polymorphic version
  • UpCast for a read only pure version.
  • IsoCast for a pure isomorphic version.
  • IsoCastE for isomorphic version that returns an error on cast failure.
Example
data := []any{1, 2, 3}

intCast := Compose(TraverseSlice[any](), DownCastP[any, int, string]())

res, err := Get(SliceOfP(intCast, 3), data)
fmt.Println(res, err)

badData := []any{1, true, 3}

res, err = Get(SliceOfP(intCast, 3), badData)
fmt.Println(res, err)

var modifyResult []any
modifyResult = MustModify(intCast, Compose3(Mul(2), FormatInt[int](10), PrependString(StringCol("Number:"))), data)
fmt.Println(modifyResult)

modifyResult = MustModify(intCast, Compose3(Mul(2), FormatInt[int](10), PrependString(StringCol("Number:"))), badData)
fmt.Println(modifyResult)
Output:

[1 2 3] <nil>
[1 3] <nil>
[Number:2 Number:4 Number:6]
[Number:2 true Number:6]

func Dropping

func Dropping[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], amount int) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

The Dropping combinator returns an optic that skips the first amount elements in the given optic and focuses on the remaining elements.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

droppingOptic := Dropping(TraverseSlice[string](), 2)

listResult := MustGet(SliceOf(droppingOptic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(droppingOptic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[gamma delta]
[alpha beta GAMMA DELTA]

func DroppingWhile

func DroppingWhile[I, S, T, A, RETI, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The DroppingWhile combinator skips the the elements of the given optic until the predicate returns false and focuses on the remaining elements.

See DroppingWhileI for an indexed version.

Example
data := []int{1, 2, 30, 4, 5}

//skips elements until a value >=10 is found.
optic := DroppingWhile(TraverseSlice[int](), Lt(10))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(optic, Mul(10), data)
fmt.Println(overResult)
Output:

[30 4 5]
[1 2 300 40 50]

func DroppingWhileI

func DroppingWhileI[I, S, T, A, RETI, RW any, DIR, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred PredicateI[I, A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The DroppingWhileI combinator skips the the elements of the given optic until the indexed predicate returns false and focuses on the remaining elements.

See DroppingWhile for a non indexed version.

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//drop elements until the index 3 is found.
optic := DroppingWhileI(

	TraverseMap[int, string](), OpI(func(index int, focus string) bool {
		return index < 3
	}))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[gamma delta]
map[1:alpha 2:beta 3:GAMMA 4:DELTA]

func DupT2

func DupT2[A any]() Optic[Void, A, A, lo.Tuple2[A, A], lo.Tuple2[A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT2 returns a Lens focusing a lo.Tuple2 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT2P for a polymorphic version

Example
data := []int{10, 20, 30}

//This optic takes slice of single ints and converts it to slice of lo.Tuple2[int,int] where A and B have duplicated values.
optic := Compose(TraverseSlice[int](), DupT2[int]())

var listRes []lo.Tuple2[int, int] = MustGet(SliceOf(optic, 3), data)
fmt.Println(listRes)

compositeReducer := ReducerT2(Sum[int](), Product[int]())
//MustReduce applies both Reducers at the same time and returns a lo.Tuple2 with the aggregated results.
var res lo.Tuple2[int, int]
var ok bool
res, ok = MustGetFirst(Reduce(optic, compositeReducer), data)

fmt.Println(res, ok)
Output:

[{10 10} {20 20} {30 30}]
{60 6000} true

func DupT2P

func DupT2P[A any, B any]() Optic[Void, A, B, lo.Tuple2[A, A], lo.Tuple2[B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT2P returns a polymorphic Lens focusing a lo.Tuple2 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT2 for a non polymorphic version

func DupT3

func DupT3[A any]() Optic[Void, A, A, lo.Tuple3[A, A, A], lo.Tuple3[A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT3 returns a Lens focusing a lo.Tuple3 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT3P for a polymorphic version

Example
data := []int{10, 20, 30}

//This optic takes slice of single ints and converts it to slice of lo.Tuple2[int,int] where A and B have duplicated values.
optic := Compose(TraverseSlice[int](), DupT3[int]())

var listRes []lo.Tuple3[int, int, int] = MustGet(SliceOf(optic, 3), data)
fmt.Println(listRes)

compositeReducer := ReducerT3(Sum[int](), Product[int](), Median[int]())
//MustReduce applies both Reducers at the same time and returns a lo.Tuple2 with the aggregated results.
var res lo.Tuple3[int, int, int]
var ok bool
res, ok = MustGetFirst(Reduce(optic, compositeReducer), data)

fmt.Println(res, ok)
Output:

[{10 10 10} {20 20 20} {30 30 30}]
{60 6000 20} true

func DupT3P

func DupT3P[A any, B any]() Optic[Void, A, B, lo.Tuple3[A, A, A], lo.Tuple3[B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT3P returns a polymorphic Lens focusing a lo.Tuple3 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT3 for a non polymorphic version

func DupT4

func DupT4[A any]() Optic[Void, A, A, lo.Tuple4[A, A, A, A], lo.Tuple4[A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT4 returns a Lens focusing a lo.Tuple4 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT4P for a polymorphic version

func DupT4P

func DupT4P[A any, B any]() Optic[Void, A, B, lo.Tuple4[A, A, A, A], lo.Tuple4[B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT4P returns a polymorphic Lens focusing a lo.Tuple4 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT4 for a non polymorphic version

func DupT5

func DupT5[A any]() Optic[Void, A, A, lo.Tuple5[A, A, A, A, A], lo.Tuple5[A, A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT5 returns a Lens focusing a lo.Tuple5 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT5P for a polymorphic version

func DupT5P

func DupT5P[A any, B any]() Optic[Void, A, B, lo.Tuple5[A, A, A, A, A], lo.Tuple5[B, B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT5P returns a polymorphic Lens focusing a lo.Tuple5 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT5 for a non polymorphic version

func DupT6

func DupT6[A any]() Optic[Void, A, A, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[A, A, A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT6 returns a Lens focusing a lo.Tuple6 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT6P for a polymorphic version

func DupT6P

func DupT6P[A any, B any]() Optic[Void, A, B, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[B, B, B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT6P returns a polymorphic Lens focusing a lo.Tuple6 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT6 for a non polymorphic version

func DupT7

func DupT7[A any]() Optic[Void, A, A, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[A, A, A, A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT7 returns a Lens focusing a lo.Tuple7 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT7P for a polymorphic version

func DupT7P

func DupT7P[A any, B any]() Optic[Void, A, B, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[B, B, B, B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT7P returns a polymorphic Lens focusing a lo.Tuple7 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT7 for a non polymorphic version

func DupT8

func DupT8[A any]() Optic[Void, A, A, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[A, A, A, A, A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT8 returns a Lens focusing a lo.Tuple8 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT8P for a polymorphic version

func DupT8P

func DupT8P[A any, B any]() Optic[Void, A, B, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[B, B, B, B, B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT8P returns a polymorphic Lens focusing a lo.Tuple8 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT8 for a non polymorphic version

func DupT9

func DupT9[A any]() Optic[Void, A, A, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[A, A, A, A, A, A, A, A, A], ReturnOne, ReadWrite, UniDir, Pure]

DupT9 returns a Lens focusing a lo.Tuple9 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT9P for a polymorphic version

func DupT9P

func DupT9P[A any, B any]() Optic[Void, A, B, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[B, B, B, B, B, B, B, B, B], ReturnOne, ReadWrite, UniDir, Pure]

DupT9P returns a polymorphic Lens focusing a lo.Tuple9 with all elements set to the source value.

Note: under modification the first element of the tuple is used. All other elements are ignored.

See: DupT9 for a non polymorphic version

func EErr

func EErr[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, Err]

The EErr re-constrain converts an Optic with any error type to Err

ERR any --> Err

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	string,
	string,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Err, Pure], //Note the path is not Pure.
] = Compose(
	ParseInt[int](10, 0),
	Mul(2),
)

var reconstrainedPure Optic[
	Void,
	string,
	string,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	Err, //EErr reconstrained to Err
] = Ret1(Rw(Bd(EErr(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrL

func EErrL[I, S, T, A, B any, RET any, RW any, DIR any, ERRL any, ERRR TPure](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERRL, ERRR]]) Optic[I, S, T, A, B, RET, RW, DIR, ERRL]

The EErrL re-constrain converts an Optic's error type to the left side of the CompositionTree where the right side is Pure.

CompositionTree[ERRL any, ERRR TPure] --> ERRL

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	string,
	string,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Err, Pure], //Note the path is not Pure.
] = Compose(
	ParseInt[int](10, 0),
	Mul(2),
)

var reconstrainedPure Optic[
	Void,
	string,
	string,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	Err, //EErrL reconstrained to Err
] = Ret1(Rw(Bd(EErrL(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrMerge

func EErrMerge[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR, ERR]]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The EErrMerge re-constrain combines identical left and right side error types of a composition tree..

CompositionTree[ERR, ERR] --> ERR

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Pure], //Note the 2 components are identical.
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	Pure, //EErrMerge reconstrained to Pure
] = Ret1(Rw(Bd(EErrMerge(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrMergeL

func EErrMergeL[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR1], ERR2]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, ERR2]]

The EErrMergeL re-constrain combines identical left and right side of the left side of a nested {CompositionTree]

CompositionTree[CompositionTree[ERR1, ERR1], ERR2] --> CompositionTree[ERR1, ERR2]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[CompositionTree[ReturnOne, ReturnOne], ReturnOne],
	CompositionTree[CompositionTree[ReadWrite, ReadWrite], ReadWrite],
	CompositionTree[CompositionTree[BiDir, BiDir], BiDir],
	CompositionTree[CompositionTree[Pure, Pure], Pure], //Note the left 2 components are identical.
] = Compose(
	Compose(
		Add(10),
		Mul(2),
	),
	Sub(1),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	CompositionTree[Pure, Pure], //EErrMergeL reconstrained the left hand side.
] = Ret1(Rw(Bd(EErrMergeL(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrMergeR

func EErrMergeR[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, CompositionTree[ERR2, ERR2]]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, ERR2]]

The EErrMergeR re-constrain combines identical left and right side of the right side of a nested {CompositionTree]

CompositionTree[ERR1, CompositionTree[ERR2, ERR2]] --> CompositionTree[ERR1, ERR2]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func EErrR

func EErrR[I, S, T, A, B any, RET any, RW any, DIR any, ERRL TPure, ERRR any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERRL, ERRR]]) Optic[I, S, T, A, B, RET, RW, DIR, ERRR]

The EErrR re-constrain converts an Optic's error type to the right side of the CompositionTree where the left side is Pure.

CompositionTree[ERRL TPure, ERRR any] --> ERRR

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	string,
	string,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Err], //Note the path is not Pure.
] = ComposeLeft(
	Mul(2),
	AsReverseGet(ParseInt[int](10, 0)),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	string,
	string,
	ReturnOne,
	ReadWrite,
	BiDir,
	Err, //EErrR reconstrained to Err
] = Ret1(Rw(Bd(EErrR(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrSwap

func EErrSwap[I, S, T, A, B any, RET any, RW any, DIR any, ERRL any, ERRR any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERRL, ERRR]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERRR, ERRL]]

The EErrSwap re-constrain swaps the left and right side of an Optic's error type CompositionTree.

CompositionTree[ERRL, ERRR] --> CompositionTree[ERRR, ERRL]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	string,
	string,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	Mul(2),
	AsReverseGet(ParseInt[int](10, 0)),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	string,
	string,
	ReturnOne,
	ReadWrite,
	BiDir,
	CompositionTree[Err, Pure], //Pure and Err have been swapped.
] = Ret1(Rw(Bd(EErrSwap(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrSwapL

func EErrSwapL[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any, ERR3 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR2, ERR1], ERR3]]

The EErrSwapL re-constrain swaps the left and right side of the left side of a nested CompositionTree.

CompositionTree[CompositionTree[ERR1, ERR2], ERR3] --> CompositionTree[CompositionTree[ERR2, ERR1], ERR3]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	string,
	string,
	CompositionTree[CompositionTree[ReturnOne, ReturnOne], ReturnOne],
	CompositionTree[CompositionTree[ReadWrite, ReadWrite], ReadOnly],
	CompositionTree[CompositionTree[BiDir, BiDir], UniDir],
	CompositionTree[CompositionTree[Pure, Err], Pure],
] = Compose(
	Compose(
		Mul(2),
		AsReverseGet(ParseInt[int](10, 0)),
	),
	PrependString(StringCol("X")),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	string,
	string,
	ReturnOne,
	ReadOnly,
	UniDir,
	CompositionTree[CompositionTree[Err, Pure], Pure], //Pure and Err have been swapped.
] = Ret1(Ro(Ud(EErrSwapL(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Getter

func EErrSwapR

func EErrSwapR[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any, ERR3 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, CompositionTree[ERR2, ERR3]]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, CompositionTree[ERR3, ERR2]]]

The EErrSwapR re-constrain swaps the left and right side of the right side of a nested CompositionTree.

CompositionTree[ERR1, CompositionTree[ERR2, ERR3]]] --> CompositionTree[ERR1, CompositionTree[ERR3, ERR2]]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func EErrTrans

func EErrTrans[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any, ERR3 any, ERR4 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR3], CompositionTree[ERR2, ERR4]]]

The EErrTrans re-constrain transposes the middle error type of a nested CompositionTree.

CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4] --> CompositionTree[CompositionTree[ERR1, ERR3], CompositionTree[ERR2, ERR4]

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[CompositionTree[ReturnOne, ReturnOne], CompositionTree[ReturnOne, ReturnOne]],
	CompositionTree[CompositionTree[ReadWrite, ReadWrite], CompositionTree[ReadWrite, ReadWrite]],
	CompositionTree[CompositionTree[BiDir, BiDir], CompositionTree[BiDir, BiDir]],
	CompositionTree[CompositionTree[Pure, Err], CompositionTree[Pure, Err]],
] = Compose4(
	Add(10),
	EErr(Mul(2)),
	Add(10),
	EErr(Mul(2)),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	CompositionTree[CompositionTree[Pure, Pure], CompositionTree[Err, Err]],
] = Ret1(Rw(Bd(EErrTrans(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrTransL

func EErrTransL[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any, ERR3 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[CompositionTree[ERR1, ERR3], ERR2]]

The EErrTransL re-constrain transposes the right element with the right child of a nested composition tree to the left.

CompositionTree[CompositionTree[ERR1, ERR2], ERR3] --> CompositionTree[CompositionTree[ERR1, ERR3], ERR2] This has the effect of removing a level of nested from the ERR2 path of the composition tree.

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[CompositionTree[ReturnOne, ReturnOne], ReturnOne],
	CompositionTree[CompositionTree[ReadWrite, ReadWrite], ReadWrite],
	CompositionTree[CompositionTree[BiDir, BiDir], BiDir],
	CompositionTree[CompositionTree[Pure, Err], Pure],
] = Compose(
	Compose(
		Add(10),
		EErr(Mul(2)),
	),
	Sub(1),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	CompositionTree[CompositionTree[Pure, Pure], Err],
] = Ret1(Rw(Bd(EErrTransL(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EErrTransR

func EErrTransR[I, S, T, A, B any, RET any, RW any, DIR any, ERR1 any, ERR2 any, ERR3 any](o Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR1, CompositionTree[ERR2, ERR3]]]) Optic[I, S, T, A, B, RET, RW, DIR, CompositionTree[ERR2, CompositionTree[ERR1, ERR3]]]

The EErrTransR re-constrain transposes the left element with the left child of a nested composition tree to the right.

CompositionTree[ERR1, CompositionTree[ERR2, ERR3]] --> CompositionTree[ERR2, CompositionTree[ERR1, ERR3]] This has the effect of removing a level of nested from the ERR2 path of the composition tree.

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func EPure

func EPure[I, S, T, A, B any, RET any, RW any, DIR any, ERR TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, Pure]

The EPure re-constrain converts an Optic with a complex but Pure error type to Pure

ERR TPure --> Pure

See:

  • EPure for a re-constrain to Pure
  • EErr for a re-constrain to Err
  • EErrL for a re-constrain to the left side of a CompositionTree
  • EErrR for a re-constrain to the Right side of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwap for a re-constrain that swaps the components of a CompositionTree
  • EErrSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • EErrSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • EErrMerge for a re-constrain that merges identical components of a CompositionTree
  • EErrMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • EErrMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • EErrTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • EErrTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • EErrTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticPure Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Pure], //Note the path is Pure.
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrainedPure Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite,
	BiDir,
	Pure, //EPure reconstrained to Pure
] = Ret1(Rw(Bd(EPure(opticPure))))

fmt.Println(reconstrainedPure.OpticType())
Output:

Iso

func EditDistance

func EditDistance[I, S, T, A, B any, RET any, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], allowedEdits EditType, equal Predicate[lo.Tuple2[A, A], ERRP], size int) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], float64, float64, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]
Example
data := []lo.Tuple2[string, string]{
	lo.T2("alpha", "alpha"),
	lo.T2("alpha", "Alpha"),
	lo.T2("alpha", "lapha"),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[string, string]](),
	EditDistance(TraverseString(), EditOSA, EqT2[rune](), 10),
)

res := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(res)
Output:

[0 1 1]

func EditDistanceI

func EditDistanceI[I, S, T, A, B any, RET any, RW any, DIR any, ERR any, ERRI any, ERRP any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], allowedEdits EditType, ixMatch Predicate[lo.Tuple2[I, I], ERRI], equal Predicate[lo.Tuple2[A, A], ERRP], size int) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], float64, float64, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, CompositionTree[ERRI, ERRP]]]
Example
data := []lo.Tuple2[string, string]{
	lo.T2("alpha", "alpha"),
	lo.T2("alpha", "Alpha"),
	lo.T2("alpha", "lapha"),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[string, string]](),
	EditDistanceI(TraverseString(), EditOSA, EqT2[int](), EqT2[rune](), 10),
)

res := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(res)
Output:

[0 1 2]

func Element

func Element[I, S, T, A, RETI, RW, DIR any, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], index int) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

The Element combinator focuses on the element of the given optic at the given 0 based index.

See :

  • AtMap for an optic that focuses an indexed value in a map.
Example
//       0123456789
data := "Lorem ipsum"

optic := Element(TraverseString(), 6)

viewResult, found := MustGetFirst(optic, data)
fmt.Println(string(viewResult), found)

modifyResult := MustModify(optic, Op(unicode.ToUpper), data)
fmt.Println(modifyResult)
Output:

i true
Lorem Ipsum

func Embed

func Embed[I, S, T, A, B any, RET any, RW TReadWrite, DIR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, B, A, T, S, ReturnOne, ReadOnly, UniDir, ERR]

The Embed combinator reverses the direction of a Prism. The result is a Getter as a Prism may focus no elements.

See:

Example
//DownCast returns a Prism (ReturnMany) as the downcast may focus nothing if the cast fails.
anyToString := DownCast[any, string]()

//Embed reverses the direction of the downCast Prism. The cast from string to any always suceeds
//So the returned optic is now a Getter (ReturnOne,ReadOnly)
stringToAny := Embed(anyToString)

var res any = MustGet(stringToAny, "alpha")
fmt.Println(res)
Output:

alpha

func Empty

func Empty[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

Empty returns a Predicate that is satisfied if the the given optic focuses no elements.

See NotEmpty for the inverse version.

Example
var result bool = MustGet(
	Empty(TraverseSlice[string]()),
	[]string{"alpha", "beta", "gamma", "delta"},
)
fmt.Println(result)

result = MustGet(
	Empty(TraverseSlice[string]()),
	[]string{},
)
fmt.Println(result)
Output:

false
true

func EncodeString

func EncodeString(encoding encoding.Encoding) Optic[Void, string, string, []byte, []byte, ReturnOne, ReadWrite, BiDir, Err]

EncodeString returns an Iso that focuses the string as a bytes with the given encoding.

Example
data := "\u03bc"

res, err := Get(
	Length(
		Compose(
			EncodeString(u.UTF8), //import u "golang.org/x/text/encoding/unicode"
			TraverseSlice[byte](),
		),
	),
	data,
)
fmt.Println(res, err)
Output:

2 <nil>

func Eq

func Eq[A comparable](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Eq returns a Predicate that is satisfied if the focused value is equal to (==) the provided constant value.

See:

  • EqOp for a Predicate that compares 2 focuses instead of a constant.
  • EqI for a version that compares indices.
Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(SliceOf(Filtered(TraverseSlice[int](), Eq(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Eq(3), data)
fmt.Println(overResult)
Output:

[3]
[false false true false false]

func EqCol

func EqCol[I comparable, A any, ERR any, PERR TPure](right Collection[I, A, ERR], eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

EqCol returns a Predicate that is satisfied if the elements of the focused Collection are all equal to (==) the elements of the provided constant Collection and element Predicate.

func EqColT2

func EqColT2[I comparable, A, ERR any, PERR TPure](eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

EqColT2 returns an BinaryOp that is satisfied if every element and index in Collection A and Collection B in focused order are equal.

See:

  • EqCol for a unary version.
  • EqColT2I for a version that supports arbitrary index types

func EqColT2I

func EqColT2I[I any, A, ERR any, IERR, PERR TPure](ixMatch Predicate[lo.Tuple2[I, I], IERR], eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

EqColT2 returns an index aware BinaryOp that is satisfied if Collection A == Collection B.

See:

  • EqColT2 for a version that simpler version that supports only comparable index types.

func EqDeep

func EqDeep[A any](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqDeep returns a Predicate that is satisfied if the focused value is reflect.DeepEqual to (==) the provided constant value.

See:

  • [DeepEqOp] for a Predicate that compares 2 focuses instead of a constant.
Example
data := []map[string]int{

	map[string]int{
		"alpha": 1,
	},

	map[string]int{
		"beta": 2,
	},
}

optic := Compose(
	TraverseSlice[map[string]int](),
	EqDeep(map[string]int{
		"alpha": 1,
	}),
)

var res []bool = MustGet(
	SliceOf(
		optic,
		2,
	),
	data,
)

fmt.Println(res)
Output:

[true false]

func EqDeepOp

func EqDeepOp[S any, A any, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

EqDeepOp returns a Predicate that is satisfied if the left focus is reflect.DeepEqual to (==) the right focus.

See EqDeep for a predicate that checks constant a value rather than 2 focuses.

Example
data := [][]map[string]int{
	{
		map[string]int{
			"alpha": 1,
		},
		map[string]int{
			"alpha": 1,
		},
	},
	{
		map[string]int{
			"alpha": 1,
		},
		map[string]int{
			"beta": 2,
		},
	},
}

optic := Compose(
	TraverseSlice[[]map[string]int](),
	EqDeepOp(
		FirstOrDefault(Index(TraverseSlice[map[string]int](), 0), nil),
		FirstOrDefault(Index(TraverseSlice[map[string]int](), 1), nil),
	),
)

var res []bool = MustGet(
	SliceOf(
		optic,
		2,
	),
	data,
)

fmt.Println(res)
Output:

[true false]

func EqDeepT2

func EqDeepT2[A any]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqDeepT2 returns an BinaryOp that is satisfied if A is reflect.DeepEqual to B.

See:

  • EqDeep for a unary version.
  • EqDeepOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[map[string]int, map[string]int]{
	lo.T2(
		map[string]int{
			"alpha": 1,
		},
		map[string]int{
			"alpha": 1,
		},
	),
	lo.T2(
		map[string]int{
			"alpha": 1,
		},
		map[string]int{
			"beta": 2,
		},
	),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[map[string]int, map[string]int]](),
	EqDeepT2[map[string]int](),
)

var res []bool = MustGet(
	SliceOf(
		optic,
		2,
	),
	data,
)

fmt.Println(res)
Output:

[true false]

func EqI

func EqI[A any, P comparable](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqI returns a PredicateI that is satisfied if the focused index is equal to (==) the provided constant value.

See:

  • Eq for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, EqI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[gamma]

func EqMap

func EqMap[K comparable, S any, PERR TPure](right map[K]S, eq Predicate[lo.Tuple2[S, S], PERR]) Optic[Void, map[K]S, map[K]S, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqMapT2 returns a Predicate that is satisfied if the elements of the focused Map are all equal to (==) the elements of the provided constant Map and element Predicate.

func EqMapT2

func EqMapT2[K comparable, S any, PERR TPure](eq Predicate[lo.Tuple2[S, S], PERR]) Optic[Void, lo.Tuple2[map[K]S, map[K]S], lo.Tuple2[map[K]S, map[K]S], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqMapT2 returns a BinaryOp that is satisfied if every element and index in Map A and Map B in focused order are equal.

See:

  • EqMap for a unary version.

func EqOp

func EqOp[S any, A comparable, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

EqOp returns a Predicate that is satisfied if the left focus is equal to (==) the right focus.

See Eq for a predicate that checks constant a value rather than 2 focuses.

Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A==B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := EqOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{1 1} {2 2}]
[true false false true]

func EqSlice

func EqSlice[A any, PERR TPure](right []A, eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, []A, []A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqSliceT2 returns a Predicate that is satisfied if the elements of the focused Slice are all equal to (==) the elements of the provided constant Slice and element Predicate.

func EqSliceT2

func EqSliceT2[A any, PERR TPure](eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[[]A, []A], lo.Tuple2[[]A, []A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqSliceT2 returns a BinaryOp that is satisfied if every element and index in Slice A and Slice B in focused order are equal.

See:

func EqString

func EqString(right string) Optic[Void, string, string, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqString returns a Predicate that is satisfied if the elements of the focused String are all equal to (==) the elements of the provided constant String and element Predicate.

func EqStringT2

EqStringT2 returns an BinaryOp that is satisfied if every element and index in String A and String B in focused order are equal.

See:

func EqT2

func EqT2[A comparable]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

EqT2 returns an BinaryOp that is satisfied if A == B.

See:

  • Eq for a unary version.
  • EqOp for a version that is applied to the focus of 2 [Operation]s.

func EqT2Of

func EqT2Of[I, S, A, RET, RW, DIR, ERR any, PERR TPure](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

The EqT2Of combinator returns an optic that compares that each focused element and it's index are equal and that both traversals focus the same number of elements.

func Error

func Error[S, A any](err error) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, BiDir, Err]

Error returns an Iso that always returns an error.

See:

  • ErrorP for a polymorphic version.
Example
data := []int{1, 2, -3, 4}

optic := Compose(
	TraverseSlice[int](),
	If(
		Lt(0),
		Error[int, int](errors.New("<0")),
		Identity[int](),
	),
)

res, err := Get(SliceOf(optic, len(data)), data)
fmt.Println(res, err)
Output:

[] <0
optic error path:
	Error(<0)
	Switch(Case(< 0 -> Error(<0))Default(Identity))
	Traverse
	SliceOf(Traverse | Switch(Case(< 0 -> Error(<0))Default(Identity)))

func ErrorAs

func ErrorAs[A error]() Optic[Void, error, error, A, A, ReturnMany, ReadWrite, BiDir, Pure]

ErrorAs returns a Prism that focuses the error as the given type or nothing if the types do not match.

See:

  • ErrorIs for an errors.Is version.
Example
optic := Catch(
	ParseInt[int32](10, 32),
	FirstOrDefault(
		Coalesce(
			Compose(
				ErrorAs[*strconv.NumError](),
				OpE(func(ctx context.Context, source *strconv.NumError) (int32, error) {
					return -1, fmt.Errorf("custom parse error of value %v", source.Num)
				}),
			),
			Throw[int32](),
		),
		-1,
	),
)

viewResult, ok, err := GetFirst(optic, "1")
fmt.Println(viewResult, ok, err)

viewResult, ok, err = GetFirst(optic, "one")
fmt.Println(viewResult, ok, err)
Output:

1 true <nil>
-1 false custom parse error of value one
optic error path:
	func1
	ErrorAs(*strconv.NumError)
	Coalesce(ErrorAs(*strconv.NumError) | func1,Throw())
	ReIndexed(Const({}),Coalesce(ErrorAs(*strconv.NumError) | func1,Throw()))
	Polymorphic(ReIndexed(Const({}),Coalesce(ErrorAs(*strconv.NumError) | func1,Throw())))
	Coalesce(Polymorphic(ReIndexed(Const({}),Coalesce(ErrorAs(*strconv.NumError) | func1,Throw()))),Const(-1))
	Filtered(< 1,Const(true),FilterContinue,FilterStop)
	Catch(ParseInt(10,32),Filtered(< 1,Const(true),FilterContinue,FilterStop),Throw())

func ErrorI

func ErrorI[I, S, A any](err error, ixMatch func(a, b I) bool) Optic[I, S, S, A, A, ReturnOne, ReadWrite, BiDir, Err]

func ErrorIP

func ErrorIP[I, S, T, A, B any](err error, ixMatch func(a, b I) bool) Optic[I, S, T, A, B, ReturnOne, ReadWrite, BiDir, Err]

func ErrorIs

func ErrorIs(target error) Optic[Void, error, error, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

ErrorIs returns a Predicate that focuses true if the error is the target error

See:

Example
data := []string{"1", "2", "three", "4"}

optic := Compose(
	TraverseSlice[string](),
	Ignore(
		ParseInt[int](10, 32),
		ErrorIs(strconv.ErrSyntax),
	),
)

var viewResult []int = MustGet(SliceOf(optic, len(data)), data)
fmt.Println(viewResult)

var modifyResult []string = MustModify(optic, Mul(10), data)
fmt.Println(modifyResult)
Output:

[1 2 4]
[10 20 three 40]

func ErrorP

func ErrorP[S, T, A, B any](err error) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, BiDir, Err]

ErrorP returns a polymorphic Iso that always returns an error.

See:

  • Error for a non polymorphic version.
Example
optic := Compose(
	TraverseSlice[any](),
	Coalesce(
		DownCastP[any, string, int](),
		ErrorP[any, any, string, int](errors.New("down cast failed")),
	),
)

res, err := Modify(optic, ParseInt[int](10, 0), []any{"1", "2", "3"})
fmt.Println(res, err)

res, err = Modify(optic, ParseInt[int](10, 0), []any{"1", false, "3"})
fmt.Println(res, err)
Output:

[1 2 3] <nil>
[] down cast failed
optic error path:
	Error(down cast failed)
	Coalesce(Cast,Error(down cast failed))
	Traverse

func Even

func Even[A Integer]() Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Even returns a predicate is satisfied if the given arithmetic value is even.

Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(SliceOf(Filtered(TraverseSlice[int](), Even[int]()), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Even[int](), data)
fmt.Println(overResult)
Output:

[2 4]
[false true false true false]

func ExprOptic

func ExprOptic[I, S, T, A, B, RET, RW, DIR, ERR any](
	exprHandler ExprHandler,
	expression func(t expr.OpticTypeExpr) expr.OpticExpression,
) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

ExprOptic returns an optic that will pass the complete expression tree to the given handler.

This can be used for example to translate optics to SQL statements.

Warning: the RET,RW,DIR constraints MUST match the abilities of the handler otherwise runtime errors will be reported instead of being reported at compile time.

An ExprOptic is constructed from 2 parameters

  • exprHandler is an ExprHandler that will be called when this optic is used in any action.
  • expr: should return the expression type. See the expr package for more information.
Example
package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/spearson78/go-optic/expr"

	. "github.com/spearson78/go-optic"
)

type ExampleExprHandler struct {
}

// Get implements ExprHandler.
func (e *ExampleExprHandler) Get(ctx context.Context, expr expr.OpticExpression, source any) (any, any, bool, error) {
	fmt.Printf("ExampleExprHandler.Get(Optic:%v,Source:%v)\n", expr.Short(), source)

	//Interpret the expr using the source as a parameter
	//Return the result

	return nil, nil, false, errors.New("getter not implemented")
}

// Modify implements ExprHandler.
func (e *ExampleExprHandler) Modify(ctx context.Context, expr expr.OpticExpression, fmapExpr expr.OpticExpression, fmap func(index any, focus any, focusErr error) (any, error), source any) (any, bool, error) {
	fmt.Printf("ExampleExprHandler.Modify(Optic:%v,Fmap:%v,Source:%v)\n", expr.Short(), fmapExpr.Short(), source)

	//Interpret the expr using the source as a parameter
	//Either map the values using an interpreter over fmapExpr or call the fmap function if the mapping should be executed in go.
	//Return the result

	return nil, false, errors.New("modify not implemented")
}

// ReverseGet implements ExprHandler.
func (e *ExampleExprHandler) ReverseGet(ctx context.Context, expr expr.OpticExpression, focus any) (any, error) {
	fmt.Printf("ExampleExprHandler.ReverseGet(Optic:%v,Focus:%v)\n", expr.Short(), focus)

	//Interpret the expr using the focus as a parameter
	//and return the result

	return nil, errors.New("reverse get not implemented")
}

// Set implements ExprHandler.
func (e *ExampleExprHandler) Set(ctx context.Context, o expr.OpticExpression, source any, val any) (any, error) {
	fmt.Printf("ExampleExprHandler.Setter(Optic:%v,Source:%v,Val:%v)\n", o.Short(), source, val)

	//Interpret the expr using the focus as a parameter
	//Set th value to val
	//Return the result

	return nil, errors.New("setter not implemented")
}

// TypeId implements ExprHandler.
func (e *ExampleExprHandler) TypeId() string {
	//This ID must be unique. Only one ExpressionHandler TypeId is allowed in the entire expression tree.
	return "ExampleExprOptic"
}

func main() {

	//This example is a stub demonstrating how an ExprOptic can be used.
	//A complete example is outside the scope of this documentation.

	intsFromDb := ExprOptic[int, string, string, int, int, ReturnMany, ReadWrite, UniDir, Err](
		&ExampleExprHandler{},
		expr.Custom("ExampleExprOptic"),
	)

	optic := Compose(
		Ordered(
			intsFromDb,
			OrderBy(Identity[int]()),
		),
		Mul(10),
	)

	//Note: even though the intsFromDb [ExprOptic] is nested in a compose and ordered it's handler takes control of executing each action completely
	//The expression tree passed to the handler is always the root optic.

	var dbConnectionString = "sqlite:example.db"

	_, err := Get(SeqEOf(optic), dbConnectionString)
	fmt.Println(err)

	_, err = Modify(optic, Mul(10), dbConnectionString)
	fmt.Println(err)

	_, err = Set(optic, 100, dbConnectionString)
	fmt.Println(err)

}
Output:

ExampleExprHandler.Get(Optic:SeqOf(Ordered(Custom(ExampleExprOptic),OrderBy(Identity)) | * 10),Source:sqlite:example.db)
getter not implemented
ExampleExprHandler.Modify(Optic:Ordered(Custom(ExampleExprOptic),OrderBy(Identity)) | * 10,Fmap:ValueI[github.com/spearson78/go-optic.Void,int].value | * 10,Source:sqlite:example.db)
modify not implemented
ExampleExprHandler.Setter(Optic:Ordered(Custom(ExampleExprOptic),OrderBy(Identity)) | * 10,Source:sqlite:example.db,Val:100)
setter not implemented

func False

func False[A any]() Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

False returns a Predicate that is never satisfied.

Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(
	SliceOf(
		Filtered(

			TraverseSlice[int](), False[int](),
		),
		len(data),
	),
	data,
)
fmt.Println(filtered)
Output:

[]

func FieldLens

func FieldLens[S, A any](fref func(source *S) *A) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

FieldLens returns a Lens focusing on a field within a struct

A FieldLens is constructed from a single function - fref: should return the address of the field within the given struct.

Note: FieldLenses are normally created by the makelens tool which also provides a convenient composition builder.

See: - PtrFieldLens for a lens that focuses on a pointer of the source. - PtrFieldLensE for a lens that focuses on a pointer of the source where the source is not expected to be nil.

Example
package main

import (
	"fmt"
	"strings"

	. "github.com/spearson78/go-optic"
)

type Person struct {
	Name    string
	Age     int `example:"age"`
	Hobbies []string
}

func main() {

	nameField := FieldLens(func(source *Person) *string { return &source.Name })
	ageField := FieldLens(func(source *Person) *int { return &source.Age })
	hobbiesField := FieldLens(func(source *Person) *[]string { return &source.Hobbies })

	data := Person{
		Name:    "Max Mustermann",
		Age:     46,
		Hobbies: []string{"eating", "sleeping"},
	}

	name := MustGet(nameField, data)
	age := MustGet(ageField, data)
	hobbies := MustGet(hobbiesField, data)

	fmt.Println(name, age, hobbies)

	olderPerson := MustSet(ageField, 47, data)
	fmt.Println(olderPerson)

	//Note: the return type is a person with hobbies converted to upper case
	var upperHobbies Person = MustModify(Compose(hobbiesField, TraverseSlice[string]()), Op(strings.ToUpper), data)
	fmt.Println(upperHobbies)

}
Output:

Max Mustermann 46 [eating sleeping]
{Max Mustermann 47 [eating sleeping]}
{Max Mustermann 46 [EATING SLEEPING]}

func FieldLensP

func FieldLensP[S, T, A, B any](get func(source *S) *A, set func(focus B, source S) T) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Pure]

func Filtered

func Filtered[I, S, T, A, RETI, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The Filtered combinator focuses on the elements of the given optic that match the given predicate.

See:

  • [FilteredBy] for a filtering combinator that yields the source instead of the focus.
  • FilteredI for an indexed version
Example
data := []int{1, 2, 30, 4, 5}

optic := Filtered(TraverseSlice[int](), Lt(10))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(optic, Add(1), data)
fmt.Println(overResult)
Output:

[1 2 4 5]
[2 3 30 5 6]

func FilteredCol

func FilteredCol[I comparable, A any, ERR any](pred Predicate[A, ERR]) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadWrite, UniDir, ERR]

FilteredCol returns a Lens that removes elements from a Collection that match a predicate

See: - FilteredColI for an index aware version - Filtered for a non collection version.

Example
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var result []int = MustModify(
	SliceToCol[int](),
	FilteredCol[int, int](
		Odd[int](),
	),
	slice,
)

fmt.Println(result)
Output:

[1 3 5 7 9]

func FilteredColI

func FilteredColI[I, A any, ERR any](pred PredicateI[I, A, ERR], ixMatch func(a, b I) bool) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadWrite, UniDir, ERR]

FilteredColI returns an index aware Lens that removes elements from an Collection that match a predicate

See: - FilteredCol for a non index aware version - FilteredI for a non collection version

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

var result map[int]string = MustModify(
	MapToCol[int, string](),
	FilteredColI[int, string](
		OpOnIx[string](
			Odd[int](),
		),
		IxMatchComparable[int](),
	),
	data,
)

fmt.Println(result)
Output:

map[1:alpha 3:gamma]

func FilteredI

func FilteredI[I, S, T, A, RETI any, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred PredicateI[I, A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The FilteredI combinator focuses on the elements of the given optic that match the given indexed predicate.

See:

  • [FilteredBy] for a filtering combinator that yields the source instead of the focus.
  • Filtered for a non indexed version
Example
data := "Lorem ipsum delor"

optic := FilteredI(

	TraverseString(), OpI(func(index int, focus rune) bool {
		return index%2 == 0
	}))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(string(listResult))

overResult := MustModify(optic, Op(unicode.ToUpper), data)
fmt.Println(overResult)
Output:

Lrmismdlr
LoReM IpSuM DeLoR

func FilteredIP

func FilteredIP[I, S, T, A, B, RETI any, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR], pred PredicateI[I, A, ERRP]) Optic[I, S, T, A, A, ReturnMany, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]

func FilteredMap

func FilteredMap[K comparable, S any, ERR any](pred Predicate[S, ERR]) Optic[Void, map[K]S, map[K]S, map[K]S, map[K]S, ReturnOne, ReadWrite, UniDir, ERR]

FilteredMap applies the Filtered operation to a Map

See: - FilteredMapI for an index aware version

Example
data := lo.T2(
	1,
	map[int]string{
		1: "alpha",
		2: "beta",
		3: "gamma",
		4: "delta",
	},
)

var getRes map[int]string = MustGet(
	Compose(
		T2B[int, map[int]string](),
		FilteredMap[int](Ne("beta")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, map[int]string] = MustModify(
	T2B[int, map[int]string](),
	FilteredMap[int](Ne("beta")), //FilteredMap can be used as an operation
	data,
)
fmt.Println(modifyRes)
Output:

map[1:alpha 3:gamma 4:delta]
{1 map[1:alpha 3:gamma 4:delta]}

func FilteredMapI

func FilteredMapI[K comparable, S any, ERR any](pred PredicateI[K, S, ERR]) Optic[Void, map[K]S, map[K]S, map[K]S, map[K]S, ReturnOne, ReadWrite, UniDir, ERR]

FilteredMapI applies the FilteredI operation to a Map

See: - FilteredMap for a non index aware version

Example
data := lo.T2(
	1,
	map[int]string{
		1: "alpha",
		2: "beta",
		3: "gamma",
		4: "delta",
	},
)

var getRes map[int]string = MustGet(
	Compose(
		T2B[int, map[int]string](),
		FilteredMapI(NeI[string](2)),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, map[int]string] = MustModify(
	T2B[int, map[int]string](),
	FilteredMapI(NeI[string](2)), //FilteredMapI can be used as an operation
	data,
)
fmt.Println(modifyRes)
Output:

map[1:alpha 3:gamma 4:delta]
{1 map[1:alpha 3:gamma 4:delta]}

func FilteredP

func FilteredP[I, S, T, A, B, RETI, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[I, S, T, A, A, ReturnMany, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]

func FilteredSlice

func FilteredSlice[A any, ERR any](pred Predicate[A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, UniDir, ERR]

FilteredSlice applies the Filtered operation to a Slice

See: - FilteredSliceI for an index aware version

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		FilteredSlice(Ne("beta")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	FilteredSlice(Ne("beta")), //FilteredSlice can be used as an operation
	data,
)
fmt.Println(modifyRes)
Output:

[alpha gamma delta]
{1 [alpha gamma delta]}

func FilteredSliceI

func FilteredSliceI[A any, ERR any](pred PredicateI[int, A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, UniDir, ERR]

FilteredSliceI applies the FilteredI operation to a Slice

See: - FilteredSlice for a non index aware version

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		FilteredSliceI(NeI[string](1)),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	FilteredSliceI(NeI[string](1)), //FilteredSliceI can be used as an operation
	data,
)
fmt.Println(modifyRes)
Output:

[alpha gamma delta]
{1 [alpha gamma delta]}

func FilteredString

func FilteredString[ERR any](pred Predicate[rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadWrite, UniDir, ERR]

FilteredString applies the Filtered operation to a String

See: - FilteredStringI for an index aware version

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		FilteredString(In('a', 'e', 'i', 'o', 'u', ' ')),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	FilteredString(In('a', 'e', 'i', 'o', 'u', ' ')),
	data,
)
fmt.Println(modifyRes)
Output:

oe iu oo i ae
{1 oe iu oo i ae}

func FilteredStringI

func FilteredStringI[ERR any](pred PredicateI[int, rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadWrite, UniDir, ERR]

FilteredStringI applies the FilteredI operation to a String

See: - FilteredString for a non index aware version

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		FilteredStringI(OpOnIx[rune](Odd[int]())),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	FilteredStringI(OpOnIx[rune](Odd[int]())),
	data,
)
fmt.Println(modifyRes)
Output:

oe pu oo i mt
{1 oe pu oo i mt}

func First

func First[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR]) Optic[I, S, T, A, A, RET, RW, UniDir, ERR]

The First combinator returns an optic that focuses the first focused element.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := TraverseSlice[string]()

var result string
var found bool
var err error
result, found, err = GetFirst(First(optic), data)
fmt.Println(result, found, err)

var overResult []string = MustModify(First(optic), Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

alpha true <nil>
[ALPHA beta gamma delta]

func FirstOrDefault

func FirstOrDefault[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR], defaultVal A) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, ERR]

The FirstOrDefault combinator returns an optic that focuses the first focused element or the default value if no elements are focused. See:

  • FirstOrDefaultI for an index aware version
  • FirstOrError for a version that returns an error
Example
optic := TraverseSlice[string]()

var result string = MustGet(FirstOrDefault(optic, "default"), []string{})
fmt.Println(result)
Output:

default

func FirstOrDefaultI

func FirstOrDefaultI[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR], defaultIndex I, defaultVal A) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, ERR]

The FirstOrDefaultI combinator returns an optic that focuses the first focused element or the default value and index if no elements are focused. See:

Example
optic := TraverseSlice[string]()

index, result := MustGetI(FirstOrDefaultI(optic, -1, "default"), []string{})
fmt.Println(index, result)
Output:

-1 default

func FirstOrError

func FirstOrError[I, S, A, RET, RW, DIR, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], err error) Optic[I, S, S, A, A, ReturnOne, RW, UniDir, Err]

The FirstOrError combinator returns an optic that focuses the first focused element or returns the given error if no elements are focused. See:

Example
data := map[string]int{
	"alpha": 0,
	"gamma": 2,
	"delta": 3,
}

optic := FirstOrError(
	Index(
		TraverseMap[string, int](),
		"beta",
	),
	errors.New("key not found"),
)

res, err := Get(optic, data)
fmt.Println(res, err)
Output:

0 key not found
optic error path:
	Error(key not found)
	Coalesce(Index(beta),Error(key not found))
	Filtered(< 1,Const(true),FilterContinue,FilterStop)

func ForEach

func ForEach[I, J, S, T, A, B, C, D any, RET, RETM any, RW any, RWM any, DIR, DIRM any, SERR any](forEach Optic[I, S, T, A, B, RET, RW, DIR, SERR], op Optic[J, A, B, C, D, RETM, RWM, DIRM, SERR]) Optic[J, S, Collection[I, B, SERR], C, D, CompositionTree[RET, RETM], RWM, UniDir, SERR]

The ForEach combinator applies op to each element focused by forEach, focusing on the Collection of results.

This can be useful to apply impure modifications to a ReadOnly forEach optic. If forEach is ReadWrite then Compose should be used instead. See:

  • IForEach for a version that supports index mapping.
Example
lookupData := map[string]string{
	"alpha": "1",
	"beta":  "2",
	"gamma": "3",
}

lookupNames := Compose(Lookup(TraverseMap[string, string](), lookupData), Some[string]())

optic := ForEach(
	EErr(lookupNames),
	ParseInt[int](10, 32),
)

var res Collection[Void, string, Err]
res, err := Modify(optic, Mul(10), "alpha")
fmt.Println(res, err)
Output:

Col[{}:10] <nil>

func ForEachI

func ForEachI[I, J, K, S, T, A, B, C, D any, RETI TReturnOne, RET, RETM any, RWI, RW any, RWM any, DIRI, DIR, DIRM any, ERRI TPure, SERR any](ixmap IxMapper[I, J, K, RETI, RWI, DIRI, ERRI], forEach Optic[I, S, T, A, B, RET, RW, DIR, SERR], op Optic[J, A, B, C, D, RETM, RWM, DIRM, SERR]) Optic[K, S, Collection[I, B, SERR], C, D, CompositionTree[RET, RETM], RWM, UniDir, SERR]

The ForEachI combinator applies op to each element focused by forEach, focusing on the Collection of results using a mapped index

This can be useful to apply impure modifications to a ReadOnly forEach optic. If forEach is ReadWrite then Compose should be used instead. See:

  • ForEach for a non index mapping version.
Example
lookupData := map[string]string{
	"alpha": "1",
	"beta":  "2",
	"gamma": "3",
}

lookupNames := ComposeLeft(Lookup(TraverseMap[string, string](), lookupData), Some[string]())

optic := ForEachI(
	IxMapLeft[string, Void](lookupNames.AsIxMatch()),
	EErr(lookupNames),
	ParseInt[int](10, 32),
)

var res Collection[string, string, Err]
res, err := Modify(optic, Mul(10), "alpha")

fmt.Println(res, err)
Output:

Col[alpha:10] <nil>

func FormatFloat

func FormatFloat[T Real](fmt byte, prec int, bitSize int) Optic[Void, T, T, string, string, ReturnOne, ReadOnly, UniDir, Pure]

FormatFloat returns an Operation that formats a float to a string.

The fmt,prec and bitSize parameters correspond to the strconv.FormatFloat parameters with the same name. See:

Example
data := []float64{1.1, 2.2, 3.3}

var composedResult []string = MustGet(
	SliceOf(
		Compose(
			TraverseSlice[float64](),
			FormatFloat[float64]('f', -1, 64),
		),
		len(data),
	),
	data,
)
fmt.Println(composedResult)
Output:

[1.1 2.2 3.3]

func FormatInt

func FormatInt[T Real](base int) Optic[Void, T, T, string, string, ReturnOne, ReadOnly, UniDir, Pure]

FormatInt returns an Operation that formats an int to a string.

The base parameters correspond to the strconv.FormatInt parameter with the same name. See:

Example
data := []int{1, 2, 3}

var composedResult []string = MustGet(
	SliceOf(
		Compose(
			TraverseSlice[int](),
			FormatInt[int](10),
		),
		len(data),
	),
	data,
)
fmt.Println(composedResult)
Output:

[1 2 3]

func GetMod

func GetMod[S, A any](
	get func(S) A,
	modify func(fmap func(focus A) A, source S) S,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An GetMod is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr : should return the expression type. See the expr package for more information.

func GetModE

func GetModE[S, A any](
	get func(ctx context.Context, source S) (A, error),
	modify func(ctx context.Context, fmap func(focus A) (A, error), source S) (S, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An GetMod is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr : should return the expression type. See the expr package for more information.

func GetModEP

func GetModEP[S, T, A, B any](
	get func(ctx context.Context, source S) (A, error),
	modify func(ctx context.Context, fmap func(focus A) (B, error), source S) (T, error),
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An GetMod is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr : should return the expression type. See the expr package for more information.

func GetModI

func GetModI[I, S, A any](
	get func(source S) (I, A),
	modify func(fmap func(index I, focus A) A, source S) S,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

func GetModIE

func GetModIE[I, S, A any](
	get func(ctx context.Context, source S) (I, A, error),
	modify func(ctx context.Context, fmap func(index I, focus A) (A, error), source S) (S, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An indexed GetMod is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.
Example
//This lens focuses on the B element of a tuple
tupleB := GetModIEP[Void, lo.Tuple2[int, int], lo.Tuple2[int, int], int, int](
	func(ctx context.Context, source lo.Tuple2[int, int]) (Void, int, error) {
		return Void{}, source.B, nil
	},
	func(ctx context.Context, fmap func(index Void, focus int) (int, error), source lo.Tuple2[int, int]) (lo.Tuple2[int, int], error) {

		focus := source.B
		newFocus, err := fmap(Void{}, focus)
		if err != nil {
			return source, err
		}

		//LensM provides access to the old and new value at the same time to allow modifications to be detected.
		if newFocus != focus {
			source.B = newFocus
		}

		return source, err
	},
	IxMatchVoid(),
	ExprCustom("ExampleGetModIE"),
)

viewResult, err := Get(tupleB, lo.T2(10, 20))
fmt.Println(viewResult, err)

overResult, err := Modify(tupleB, Mul(2), lo.T2(10, 20))
fmt.Println(overResult, err)
Output:

20 <nil>
{10 40} <nil>

func GetModIEP

func GetModIEP[I, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	modify func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An indexed GetMod is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

func GetModIP

func GetModIP[I, S, T, A, B any](
	get func(source S) (I, A),
	modify func(fmap func(index I, focus A) B, source S) T,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An indexed GetMod is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

func GetModP

func GetModP[S, T, A, B any](
	get func(S) A,
	modify func(fmap func(focus A) B, source S) T,
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens like optic with a Traversal style modify function. The modify function provides access to the old and new focus values at the same time. This can be used to detect which modifications were made to the focus.

The following constructors are available.

An GetMod is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr : should return the expression type. See the expr package for more information.

func Getter

func Getter[S, A any](
	getFnc func(source S) A,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for a Getter optic. Lenses focus on a single element.

The following constructors are available.

A getter is constructed from 2 functions

  • get : should return the single value focused by the lens
  • expr: should return the expression type. See the expr package for more information.
Example
//This Getter focuses on the B element of a tuple
tupleB := Getter[lo.Tuple2[int, int], int](
	func(source lo.Tuple2[int, int]) int {
		return source.B
	},
	ExprCustom("ExampleGetter"),
)

var viewResult int = MustGet(tupleB, lo.T2(10, 20))
fmt.Println(viewResult)
Output:

20

func GetterE

func GetterE[S, A any](
	getFnc func(ctx context.Context, source S) (A, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for a Getter optic. Lenses focus on a single element.

The following constructors are available.

A getter is constructed from 2 functions

  • get : should return the single value focused by the lens
  • expr: should return the expression type. See the expr package for more information.
Example
//This Getter focuses on the B element of a string tuple and converts it to an int
//reporting the error in case of conversion failure
tupleB := GetterE[lo.Tuple2[string, string], int](
	func(ctx context.Context, source lo.Tuple2[string, string]) (int, error) {
		intFocus, err := strconv.ParseInt(source.B, 10, 32)
		return int(intFocus), err
	},
	ExprCustom("ExampleGetterR"),
)

//Note the result is an int even though the tuple element is a string.
var viewResult int
viewResult, err := Get(tupleB, lo.T2("10", "20"))
fmt.Println(viewResult, err)

_, err = Get(tupleB, lo.T2("10", "twenty"))
fmt.Println(err)
Output:

20 <nil>
strconv.ParseInt: parsing "twenty": invalid syntax
optic error path:
	Custom(ExampleGetterR)

func GetterI

func GetterI[I, S, A any](
	getFnc func(source S) (I, A),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for a Getter optic. Lenses focus on a single element.

The following constructors are available.

A getter is constructed from 2 functions

  • get : should return the single value focused by the lens
  • expr: should return the expression type. See the expr package for more information.
Example
//This Getter focuses on the B element of a tuple with an index
tupleB := GetterI[int, lo.Tuple2[int, int], int](
	func(source lo.Tuple2[int, int]) (int, int) {
		return 1, source.B
	},
	func(indexA, indexB int) bool {
		return indexA == indexB
	},
	ExprCustom("ExampleGetterI"),
)

var viewIndex, viewResult int = MustGetI(tupleB, lo.T2(10, 20))
fmt.Println(viewIndex, viewResult)
Output:

1 20

func GetterIE

func GetterIE[I, S, A any](
	getFnc func(ctx context.Context, source S) (I, A, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for a Getter optic. Lenses focus on a single element.

The following constructors are available.

A getter is constructed from 2 functions

  • get : should return the single value focused by the lens
  • expr: should return the expression type. See the expr package for more information.
Example
//This Getter converts the b elements of a string tuple to an int, reporting any conversion errors encountered.
//It is polymorphic so is able to return an int tuple even through the source type is a string string
parseInt := CombiGetter[Err, int, lo.Tuple2[string, string], lo.Tuple2[string, string], int, int](
	func(ctx context.Context, source lo.Tuple2[string, string]) (int, int, error) {
		intFocus, err := strconv.ParseInt(source.B, 10, 32)
		return 1, int(intFocus), err
	},
	IxMatchComparable[int](),
	ExprCustom("ExampleGetterF"),
)

var result int
result, err := Get(parseInt, lo.T2("alpha", "10"))

fmt.Println(result, err)

_, err = Get(parseInt, lo.T2("alpha", "ten"))

fmt.Println(err.Error())
Output:

10 <nil>
strconv.ParseInt: parsing "ten": invalid syntax
optic error path:
	Custom(ExampleGetterF)

func Grouped

func Grouped[I, S, T, A, B, RET, RW, DIR, ERR any, RS, RR, RERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], reducer ReductionP[RS, A, RR, RERR]) Optic[I, S, S, RR, RR, RET, ReadOnly, UniDir, CompositionTree[ERR, RERR]]

The Grouped combinator reduces all focuses with the same index using the given reducer.

Example
data := []int{1, 2, 3, 4, 5, 6, 4, 3, 2, 1, 4}

res, err := Get(
	SliceOf(
		Grouped(
			SelfIndex(TraverseSlice[int](), EqT2[int]()),
			FirstReducer[int](),
		),
		len(data),
	),
	data,
)

fmt.Println(res, err)
Output:

[1 2 3 4 5 6] <nil>

func Gt

func Gt[A cmp.Ordered](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Gt returns a Predicate that is satisfied if the focused value is greater than (>) the provided constant value.

See:

  • GtOp for a Predicate that compares 2 focuses instead of a constant.
  • GtI for a version that compares indices.
Example
data := []int{1, 2, 3, 4, 5}

var filtered []int = MustGet(SliceOf(Filtered(TraverseSlice[int](), Gt(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Gt(3), data)
fmt.Println(overResult)
Output:

[4 5]
[false false false true true]

func GtI

func GtI[A any, P cmp.Ordered](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

GtI returns a PredicateI that is satisfied if the focused index is greater than (>) the provided constant value.

See:

  • Gt for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, GtI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[delta]

func GtOp

func GtOp[S any, A cmp.Ordered, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

GtOp returns a Predicate that is satisfied if the left focus is greater than (>) the right focus.

See Gt for a predicate that checks constant a value rather than 2 focuses.

Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A>B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := GtOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{2 1}]
[false false true false]

func GtT2

func GtT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

GtT2 returns an BinaryOp that is satisfied if A > B.

See:

  • Gt for a unary version.
  • GtOp for a version that is applied to the focus of 2 [Operation]s.

func Gte

func Gte[A cmp.Ordered](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Gte returns a Predicate that is satisfied if the focused value is greater than or equal to (>=) the provided constant value.

See GteOp for a Predicate that compares 2 focuses instead of a constant.

Example
data := []int{1, 2, 3, 4, 5}

var filtered []int = MustGet(SliceOf(Filtered(TraverseSlice[int](), Gte(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Gte(3), data)
fmt.Println(overResult)
Output:

[3 4 5]
[false false true true true]

func GteI

func GteI[A any, P cmp.Ordered](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

GteI returns a PredicateI that is satisfied if the focused index is greater than or equal to than (>=) the provided constant value.

See:

  • Gte for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, GteI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[gamma delta]

func GteOp

func GteOp[S any, A cmp.Ordered, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

GteOp returns a Predicate that is satisfied if the left focus is greater than or equals to (>=) the right focus.

See:

  • Gt for a predicate that checks constant a value rather than 2 focuses.
  • GteI for a version that compares indices.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A>=B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := GteOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{1 1} {2 1} {2 2}]
[true false true true]

func GteT2

func GteT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

GteT2 returns an BinaryOp that is satisfied if A >= B.

See:

  • Gte for a unary version.
  • GteOp for a version that is applied to the focus of 2 [Operation]s.

func Identity

func Identity[S any]() Optic[Void, S, S, S, S, ReturnOne, ReadWrite, BiDir, Pure]

Identity returns an Iso that focuses on the source.

Example
data := []int{5, 2, 3, 1, 4}

res := MustGet(
	SliceOf(
		Ordered(
			TraverseSlice[int](),
			OrderBy(
				Identity[int](), //Order by slice value
			),
		),
		len(data),
	),
	data,
)
fmt.Println(res)
Output:

[1 2 3 4 5]

func IdentityI

func IdentityI[I, S, T any](i I, ixMatch func(a, b I) bool) Optic[I, S, S, S, S, ReturnOne, ReadWrite, BiDir, Pure]

IdentityIP returns an index aware polymorphic Iso that focuses on the source and given index.

func IdentityIP

func IdentityIP[I, S, T any](i I, ixMatch func(a, b I) bool) Optic[I, S, T, S, T, ReturnOne, ReadWrite, BiDir, Pure]

IdentityIP returns an index aware polymorphic Iso that focuses on the source and given index.

func IdentityP

func IdentityP[S, T any]() Optic[Void, S, T, S, T, ReturnOne, ReadWrite, BiDir, Pure]

IdentityP returns a polymorphic Iso that focuses on the source.

func If

func If[I, S, T, A, B, RETT, RETF, RWT, RWF, DIRT, DIRF, ERRP, ERRT, ERRF any](condition Predicate[S, ERRP], onTrue Optic[I, S, T, A, B, RETT, RWT, DIRT, ERRT], onFalse Optic[I, S, T, A, B, RETF, RWF, DIRF, ERRF]) Optic[I, S, T, A, B, CompositionTree[RETT, RETF], CompositionTree[RWT, RWF], UniDir, CompositionTree[CompositionTree[ERRT, ERRF], ERRP]]

If returns an Optic that executes either the onTrue or onFalse operation depending on the result of the condition.

Example
data := []int{1, 2, 3, 0, 4, 5}

ixOp := If(
	OpOnIx[int](Even[int]()), //Check for even index
	OpToOpI[int](Mul(10)),    //Multiple even indexes by 10
	OpToOpI[int](Mul(100)),   //Multiple odd indexes by 100
)

var result []int = MustModifyI(TraverseSlice[int](), ixOp, data)
fmt.Println(result)
Output:

[10 200 30 0 40 500]

func Ignore

func Ignore[I, S, A, RET, RW, DIR, ERR any, PERR TPure](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], pred Predicate[error, PERR]) Optic[I, S, S, A, A, ReturnMany, RW, DIR, Pure]

The Ignore combinator returns an optic that ignores errors that match the given predicate. under modification the original values are retained.

Note: Ignore does not ignore the context.DeadlineExceeded or context.Cancelled errors.

See:

  • Catch for an optic that can handle errors.
Example
data := []string{"1", "2", "three", "4"}

optic := Compose(TraverseSlice[string](), Ignore(ParseInt[int](10, 32), Const[error](true)))

var viewResult []int = MustGet(SliceOf(optic, len(data)), data)
fmt.Println(viewResult)

var modifyResult []string = MustModify(optic, Mul(10), data)
fmt.Println(modifyResult)
Output:

[1 2 4]
[10 20 three 40]

func IgnoreWrite

func IgnoreWrite[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, S, A, B, RET, ReadWrite, UniDir, ERR]

The IgnoreWrite modifes the given optic to be ReadWrite at the cost of ignoring any updates the original source is returned instead. This can be useful for making Const ReadWrite.

func In

func In[A comparable](right ...A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

In returns a Predicate that is satisfied if the source value is present in a list of values.

See:

Example
vowels := In('a', 'e', 'i', 'o', 'u')

index, vowel, found := MustGetFirstI(Filtered(TraverseString(), vowels), "hello world")
fmt.Println(index, string(vowel), found)
Output:

1 e true

func InT2

func InT2[A comparable]() Optic[Void, lo.Tuple2[A, []A], lo.Tuple2[A, []A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

func Index

func Index[I, S, T, A, RETI any, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], index I) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

The Index combinator returns an optic that focuses on the given index in the given optic.

Note: multiple elements may share the same index. Note: Index is not able to add or remove elements.

See:

  • Element for an optic that focuses on a element by position.
  • AtMap for an optic that is able to add/remove elements from a map.
  • Lookup for a version that looks up an index in a fixed source.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := Index(TraverseMap[int, string](), 3)

viewResult, found := MustGetFirst(optic, data)
fmt.Println(viewResult, found)

var modifyResult map[int]string = MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(modifyResult)

//Note: index cannot add new elements

setResult := MustSet(Index(TraverseMap[int, string](), 5), "epsilon", data)
fmt.Println(setResult)
Output:

gamma true
map[1:alpha 2:beta 3:GAMMA 4:delta]
map[1:alpha 2:beta 3:gamma 4:delta]

func Indexing

func Indexing[I, RETI, S, T, A, B, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[int, S, T, A, B, RETI, RW, UniDir, ERR]

The Indexing combinator returns an optic where the index is replaced with an integer position.

See ReIndexed for a version that replaces the index with an arbitrary value.

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := Indexing(TraverseMap[string, int]())

viewResult := MustGet(SliceOf(WithIndex(optic), 4), data)
fmt.Println(viewResult)

var modifyResult map[string]int = MustModifyI(optic, OpI(func(index int, focus int) int {
	if index%2 == 0 {
		return focus * 10
	}
	return focus
}), data)
fmt.Println(modifyResult)
Output:

[0:1 1:2 2:4 3:3]
map[alpha:10 beta:2 delta:40 gamma:3]

func Indices

func Indices[I, S, T, A, RET, RW, DIR, ERR, ERRP any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR], pred Predicate[I, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The Indices combinator focuses on elements in the given optic where the predicate matches the elements index.

See:

  • FilteredI for a more general filter that has access to both the index and value
  • Filtered for a non indexed version
Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := Indices(

	TraverseSlice[string](), Op(func(index int) bool {
		return index%2 == 0
	}))

viewResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(viewResult)

var modifyResult []string = MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(modifyResult)
Output:

[alpha gamma]
[ALPHA beta GAMMA delta]

func Involuted

func Involuted[S any](
	getter func(source S) S,
	exprDef ExpressionDef,
) Optic[Void, S, S, S, S, ReturnOne, ReadWrite, BiDir, Pure]

Constructor for the Involuted case of the Iso optic. This constructor is pure and non polymorphic

An involuted is an iso where the conversion to and from the result is the same. e.g. negation of a integer.

The following constructors are available.

An involuted iso is constructed from 2 functions

  • getter : should convert the source to the result.
  • expr: should return the expression type. See the expr package for more information.

See:

  • Iso for a version where the conversion to and from the result is different.
Example
//Negating a value is its own inverse. We can use an involuted here.
negate := Involuted[int](
	func(i int) int {
		return -i
	},
	ExprCustom("ExampleInvoluted"),
)

viewResult := MustGet(negate, 1)
fmt.Println(viewResult)

//For involuted isos ReView is equivalent to View
reViewResult := MustReverseGet(negate, 1)
fmt.Println(reViewResult)

data := []int{1, 2, 3}

//The Add(1) is operating in a negated context the negative value is converted back to a positive number in the result.
//This has the effect of making Add(1) subtract 1 from the value
overResult := MustModify(Compose(TraverseSlice[int](), negate), Add(1), data)
fmt.Println(overResult)
Output:

-1
-1
[0 1 2]

func InvolutedE

func InvolutedE[S any](
	getter func(ctx context.Context, source S) (S, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, S, S, ReturnOne, ReadWrite, BiDir, Err]

Constructor for the Involuted case of the Iso optic. This constructor is pure and non polymorphic

An involuted is an iso where the conversion to and from the result is the same. e.g. negation of a integer.

The following constructors are available.

An involuted iso is constructed from 2 functions

  • getter : should convert the source to the result.
  • expr: should return the expression type. See the expr package for more information.

See:

  • IsoE for a version where the conversion to and from the result is different.

func Iso

func Iso[S, A any](
	getter func(source S) A,
	reverse func(focus A) S,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Constructor for an Iso optic. Iso's perform a lossless conversion between 2 types. This constructor is pure and non polymorphic

The following constructors are available.

An iso is constructed from 3 functions

  • getter : should convert the source type to the result type.
  • reverse : should convert the result type back to the source type
  • expr: should return the expression type. See the expr package for more information.

See:

  • Involuted for a version where the getter and reverse are identical.
Example
//Converting between celsius an iso is lossless.
toFahrenheit := Iso[float64, float64](
	func(celsius float64) float64 {
		return (celsius * (9.0 / 5.0)) + 32.0
	},
	func(fahrenheit float64) float64 {
		return (fahrenheit - 32.0) * (5.0 / 9.0)
	},
	ExprCustom("ExampleIso"),
)

viewResult := MustGet(toFahrenheit, 32.0)
fmt.Println(viewResult)

//ReView peforms the reverse fahrenheit to celsius comversion
reViewResult := MustReverseGet(toFahrenheit, 89.6)
fmt.Println(reViewResult)

data := map[string]float64{
	"freeze": 0.0,
	"body":   37.0,
	"boil":   100.0,
}

//Isos can be composed to perform operations within the converted context.
//In this case Add(1.0) will add 1 fahrenheit to the values
//But the result is returned back to celsius
overComposedResult := MustModify(Compose(TraverseMap[string, float64](), toFahrenheit), Add(1.0), data)
fmt.Println(overComposedResult)

//Isos can be used directly as the operation in the Over action
//This converts the values to fahrenheit in the result
overResult := MustModify(TraverseMap[string, float64](), toFahrenheit, data)
fmt.Println(overResult)
Output:

89.6
32
map[body:37.555555555555564 boil:100.55555555555556 freeze:0.5555555555555556]
map[body:98.60000000000001 boil:212 freeze:32]

func IsoCast

func IsoCast[S, A any]() Optic[Void, S, S, A, A, ReturnOne, ReadWrite, BiDir, Pure]

IsoCast returns a Iso that performs a safe type cast from S to A and back from A to S The cast is declared safe by the user. If the cast fails a panic will occur.

See:

  • IsoCastP for a polymorphic version
  • DownCast for a version that ignores cast errors
  • UpCast for an impure version

Warning: if the types are not compatible ReverseGet will return an error.

Example
data := []string{"alpha", "beta", "gamma"}

optic := Compose(TraverseSlice[string](), IsoCast[string, []byte]()) //Casting string to []byte and back is always safe.

var res [][]byte = MustGet(SliceOf(optic, 3), data)
fmt.Println(res)

var result []string = MustModify(
	Compose3(
		TraverseSlice[string](),
		IsoCast[string, []byte](),
		TraverseSlice[byte](),
	),
	Add[byte](1),
	data,
)

fmt.Println(result)
Output:

[[97 108 112 104 97] [98 101 116 97] [103 97 109 109 97]]
[bmqib cfub hbnnb]

func IsoCastE

func IsoCastE[S, A any]() Optic[Void, S, S, A, A, ReturnOne, ReadWrite, BiDir, Err]

IsoCastE returns a Iso that performs an cast from S to A and back from A to S If the cast fails an error will occur.

See:

Example
data := []any{1, 2, 3}

intCast := Compose(TraverseSlice[any](), IsoCastE[any, int]())

res, err := Get(SliceOf(intCast, 3), data)
fmt.Println(res, err)

badData := []any{1, true, 3}

res, err = Get(SliceOf(intCast, 3), badData)
fmt.Println(res, err)

var modifyResult []any
modifyResult, err = Modify(intCast, Mul(2), data)
fmt.Println(modifyResult, err)

modifyResult, err = Modify(intCast, Mul(2), badData)
fmt.Println(modifyResult, err)
Output:

[1 2 3] <nil>
[] cast failed interface {} -> int for bool
optic error path:
	Cast
	Traverse
	SliceOf(Traverse | Cast)

[2 4 6] <nil>
[] cast failed interface {} -> int for bool
optic error path:
	Cast
	Traverse

func IsoCastEP

func IsoCastEP[S, T, A, B any]() Optic[Void, S, T, A, B, ReturnOne, ReadWrite, BiDir, Err]

IsoCastEP returns a polymorphic Iso that performs a cast from S to A and back from B to T If the cast fails an error will occur.

See:

Example
data := []any{1, 2, 3}

intCast := Compose(TraverseSliceP[any, []rune](), IsoCastEP[any, []rune, int, string]())

res, err := Get(SliceOfP(intCast, 3), data)
fmt.Println(res, err)

badData := []any{1, true, 3}

res, err = Get(SliceOfP(intCast, 3), badData)
fmt.Println(res, err)

var modifyResult [][]rune
modifyResult, err = Modify(intCast, Op(strconv.Itoa), data)
fmt.Println(modifyResult, err)

modifyResult, err = Modify(intCast, Op(strconv.Itoa), badData)
fmt.Println(modifyResult, err)
Output:

[1 2 3] <nil>
[] cast failed interface {} -> int for bool
optic error path:
	Cast
	Traverse
	SliceOf(Traverse | Cast)

[[49] [50] [51]] <nil>
[] cast failed interface {} -> int for bool
optic error path:
	Cast
	Traverse

func IsoCastP

func IsoCastP[S, T, A, B any]() Optic[Void, S, T, A, B, ReturnOne, ReadWrite, BiDir, Pure]

IsoCastP returns a polymorphic Iso that performs a safe type cast from S to A and in reverse from B to T The cast is declared safe by the user. If the cast fails a panic will occur.

See:

  • IsoCast for a non polymorphic version

Warning: if the types are not compatible ReverseGet will return an error.

Example
data := []byte{'a', 'l', 'p', 'h', 'a'}

optic := IsoCastP[[]byte, []rune, string, string]() //Casting []byte to string and string to []rune is always safe.

var res string = MustGet(optic, data)
fmt.Println(res)

var modifyRes []rune = MustModify(
	optic,
	Op(strings.ToUpper),
	data,
)

fmt.Println(string(modifyRes))
Output:

alpha
ALPHA

func IsoE

func IsoE[S, A any](
	getter func(ctx context.Context, source S) (A, error),
	reverse func(ctx context.Context, focus A) (S, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, BiDir, Err]

An iso is constructed from 3 functions

  • getter : should convert the source type to the result type.
  • reverse : should convert the result type back to the source type
  • expr: should return the expression type. See the expr package for more information.

See:

  • [InvolutedR] for a version where the getter and reverse are identical.
Example
//Converting between string and int is lossless in the cases it can be parsed
//An IsoR can be used to handle the error conditions
parseInt := IsoE[string, int](
	func(ctx context.Context, source string) (int, error) {
		intVal, err := strconv.ParseInt(source, 10, 32)
		return int(intVal), err
	},
	func(ctx context.Context, i int) (string, error) {
		return strconv.Itoa(i), nil
	},
	ExprCustom("ExampleIsoR"),
)

viewResult, err := Get(parseInt, "1")
fmt.Println(viewResult, err)

_, err = Get(parseInt, "one")
fmt.Println(err.Error())

//ReView performs the reverse int to string
reViewResult, err := ReverseGet(parseInt, 1)
fmt.Println(reViewResult, err)

data := []string{"1", "2", "3"}

//Isos can be composed to perform operations within the converted context.
//In this case Add(1) will add 1 the int values
//But the result is returned back to string
var overComposedResult []string
overComposedResult, err = Modify(Compose(TraverseSlice[string](), parseInt), Add(1), data)
fmt.Println(overComposedResult, err)

//Isos can be used directly as the operation in the Over action
//This converts the values to int in the result
var overResult []int
overResult, err = Modify(TraverseSliceP[string, int](), parseInt, data)
fmt.Println(overResult, err)
Output:

1 <nil>
strconv.ParseInt: parsing "one": invalid syntax
optic error path:
	Custom(ExampleIsoR)

1 <nil>
[2 3 4] <nil>
[1 2 3] <nil>

func IsoEP

func IsoEP[S, T, A, B any](
	getter func(ctx context.Context, source S) (A, error),
	reverse func(ctx context.Context, focus B) (T, error),
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, BiDir, Err]

Constructor for an Iso optic. Iso's perform a lossless conversion between 2 types. This constructor is impure , non indexed and polymorphic

The following constructors are available.

An iso is constructed from 3 functions

  • getter : should convert the source type to the result type.
  • reverse : should convert the result type back to the source type
  • expr: should return the expression type. See the expr package for more information.

See:

  • [InvolutedR] for a version where the getter and reverse are identical.
Example
//Polymorphic Isos can be useful when combined with other polymorphic optics
parseInt := IsoEP[string, int, int, int](
	func(ctx context.Context, source string) (int, error) {
		intVal, err := strconv.ParseInt(source, 10, 32)
		return int(intVal), err
	},
	func(ctx context.Context, focus int) (int, error) {
		return focus, ctx.Err()
	},
	ExprCustom("ExampleIsoF"),
)

var viewResult int
viewResult, err := Get(parseInt, "1")
fmt.Println(viewResult, err)

//ReView passes calls the reverse function.
var reViewResult int
reViewResult, err = ReverseGet(parseInt, 1)
fmt.Println(reViewResult, err)

//The polymorphic traversal expects a conversion from int to string. A non polymorphic iso would convert back to []string
var overResult []int
overResult, err = Modify(Compose(TraverseSliceP[string, int](), parseInt), Add(1), []string{"1", "2", "3"})
fmt.Println(overResult, err)
Output:

1 <nil>
1 <nil>
[2 3 4] <nil>

func IsoP

func IsoP[S, T, A, B any](
	getter func(source S) A,
	reverse func(focus B) T,
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, BiDir, Pure]

Constructor for an Iso optic. Iso's perform a lossless conversion between 2 types. This constructor is pure , non indexed and polymorphic

The following constructors are available.

An iso is constructed from 3 functions

  • getter : should convert the source type to the result type.
  • reverse : should convert the result type back to the source type
  • expr: should return the expression type. See the expr package for more information.

See:

  • Involuted for a version where the getter and reverse are identical.
Example
//Polymorphic Isos can be useful when combined with other polymorphic optics
toFloat := IsoP[int, float64, float64, float64](
	//getter
	func(source int) float64 {
		return float64(source)
	},
	//reverse
	func(focus float64) float64 {
		return focus
	},
	ExprCustom("ExampleIsoP"),
)

var viewResult float64 = MustGet(toFloat, 1)
fmt.Println(viewResult)

//ReView passes calls the reverse function.
var reViewResult float64 = MustReverseGet(toFloat, 1.5)
fmt.Println(reViewResult)

//The polymorphic traversal expects a conversion from int to float64. A non polymorphic iso would convert back to the source type
var overResult []float64 = MustModify(Compose(TraverseSliceP[int, float64](), toFloat), Add(0.5), []int{1, 2, 3})
fmt.Println(overResult)
Output:

1
1.5
[1.5 2.5 3.5]

func Iteration

func Iteration[S, A any](
	seq func(source S) iter.Seq[A],
	lengthGetter func(source S) int,
	exprDef ExpressionDef,
) Optic[int, S, S, A, A, ReturnMany, ReadOnly, UniDir, Pure]

Constructor for an Iteration optic. Iterations focus on multiple elements.

The following constructors are available.

An Iteration is constructed from 3 functions

  • iter : should iterates over the values in the source. yielding errors for individual values as needed.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This iteration iterates of the elements of an []int
iterateSlice := Iteration[[]int, int](
	//iter
	func(source []int) iter.Seq[int] {
		return func(yield func(focus int) bool) {
			for _, focus := range source {
				//If yield returns false iteration must be stopped
				if !yield(focus) {
					break
				}
			}
		}
	},
	//lengthGetter
	func(source []int) int {
		return len(source)
	},
	ExprCustom("ExampleIteration"),
)

for val := range MustGet(SeqOf(Compose(iterateSlice, Mul(10))), []int{1, 2, 3}) {
	fmt.Println(val)
}
Output:

10
20
30

func IterationE

func IterationE[S, A any](
	seq func(ctx context.Context, source S) iter.Seq2[A, error],
	lengthGetter LengthGetterFunc[S],
	exprDef ExpressionDef,
) Optic[int, S, S, A, A, ReturnMany, ReadOnly, UniDir, Err]

Constructor for an Iteration optic. Iterations focus on multiple elements.

The following constructors are available.

An Iteration is constructed from 3 functions

  • iter : should iterates over the values in the source. yielding errors for individual values as needed.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This Iteration converts the elements of a string slice to ints, reporting any conversion errors encountered.
//It is non polymorphic so any modification actions still return a []string
parseInts := IterationE[[]string, int](
	//iter
	func(ctx context.Context, source []string) iter.Seq2[int, error] {
		return func(yield func(focus int, err error) bool) {
			for _, strFocus := range source {
				intFocus, err := strconv.ParseInt(strFocus, 10, 32)
				//errors are reported to the caller by yielding. The caller can decide to stop iteration by returning false from the yield function.
				if !yield(int(intFocus), err) {
					//If yield returns false iteration must be stopped
					break
				}
			}
		}
	},
	//Length getter, nil will use the iterator to calculate the length
	nil,
	ExprCustom("ExampleIterationE"),
)

seq, err := Get(SeqEOf(Compose(parseInts, Mul(10))), []string{"1", "2", "3"})
if err != nil {
	log.Fatal(err)
}

for val := range seq {
	res, err := val.Get()
	fmt.Println(res, err)
}

seq, err = Get(SeqEOf(Compose(parseInts, Mul(10))), []string{"1", "two", "3"})
if err != nil {
	log.Fatal(err)
}
for val := range seq {
	res, err := val.Get()
	fmt.Println(res, err)
}

//10 <nil>
//20 <nil>
//30 <nil>
//10 <nil>
//0 strconv.ParseInt: parsing "two": invalid syntax
//optic error path:
//	Custom(ExampleIterationR)
//30 <nil>

func IterationI

func IterationI[I, S, A any](
	seq func(source S) iter.Seq2[I, A],
	lengthGetter func(source S) int,
	ixget func(source S, index I) iter.Seq2[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadOnly, UniDir, Pure]

An indexed Iteration is constructed from 5 functions

  • iter : should iterates over the values in the source. yielding errors for individual values as needed.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This Iteration iterates of the elements of an []int including the index of the element
iterateSlice := IterationI[int, []int, int](
	//iter
	func(source []int) iter.Seq2[int, int] {
		return func(yield func(index int, focus int) bool) {
			for index, focus := range source {
				//If yield returns false iteration must be stopped
				if !yield(index, focus) {
					break
				}
			}
		}
	},
	//length getter
	func(source []int) int {
		return len(source)
	},
	//ixget
	func(source []int, index int) iter.Seq2[int, int] {
		return func(yield func(index int, focus int) bool) {
			yield(index, source[index])
		}
	},
	//ix match
	func(indexA, indexB int) bool {
		return indexA == indexB
	},
	ExprCustom("ExampleIterationI"),
)

for i, val := range MustGet(SeqIOf(ComposeLeft(iterateSlice, Mul(10))), []int{1, 2, 3}) {
	fmt.Println(i, val)
}
Output:

0 10
1 20
2 30

func IterationIE

func IterationIE[I, S, A any](
	iterate func(ctx context.Context, source S) SeqIE[I, A],
	lengthGetter LengthGetterFunc[S],
	ixget func(ctx context.Context, index I, source S) SeqIE[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadOnly, UniDir, Err]

Constructor for an Iteration optic. Iterations focus on multiple elements.

The following constructors are available.

An indexed Iteration is constructed from 5 functions

  • iter : should iterates over the values in the source. yielding errors for individual values as needed.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
parseInts := IterationIE[int, []string, int](
	func(ctx context.Context, source []string) SeqIE[int, int] {
		return func(yield func(ValueIE[int, int]) bool) {
			for index, strFocus := range source {
				intFocus, err := strconv.ParseInt(strFocus, 10, 0)
				//errors are reported to the caller by yielding. The caller can decide to stop iteration by returning false from the yield function.
				if !yield(ValIE(index, int(intFocus), err)) {
					//If yield returns false iteration must be stopped
					break
				}
			}
		}
	},
	//Length getter nil will use the iterate function to calculate the length,
	nil,
	//ixget
	func(ctx context.Context, index int, source []string) SeqIE[int, int] {
		return func(yield func(ValueIE[int, int]) bool) {
			intFocus, err := strconv.ParseInt(source[index], 10, 0)
			//errors are reported to the caller by yielding
			yield(ValIE(index, int(intFocus), err))
		}
	},
	IxMatchComparable[int](),
	ExprCustom("ExampleIterationIE"),
)

seq, err := Get(SeqIEOf(Compose(parseInts, Mul(10))), []string{"1", "2", "3"})
if err != nil {
	log.Fatal(err)
}
for val := range seq {
	index, res, err := val.Get()
	fmt.Println(index, res, err)
}

seq, err = Get(SeqIEOf(Compose(parseInts, Mul(10))), []string{"1", "two", "3"})
if err != nil {
	log.Fatal(err)
}
for val := range seq {
	index, res, err := val.Get()
	fmt.Println(index, res, err)
}

//0 10 <nil>
//1 20 <nil>
//2 30 <nil>
//3 10 <nil>
//4 0 strconv.ParseInt: parsing "two": invalid syntax
//optic error path:
//	Custom(ExampleIterationF)
//5 30 <nil>

func Last

func Last[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR]) Optic[I, S, T, A, A, RET, RW, UniDir, ERR]

The Last combinator returns an optic that focuses the last focused element.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

optic := TraverseSlice[string]()

var result string
var found bool
var err error
result, found, err = GetFirst(Last(optic), data)
fmt.Println(result, found, err)

var overResult []string = MustModify(Last(optic), Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

delta true <nil>
[alpha beta gamma DELTA]

func LastOrDefault

func LastOrDefault[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR], defaultVal A) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, ERR]

The LastOrDefault combinator returns an optic that focuses the last focused element or the default value if no elements are focused. See:

func LastOrDefaultI

func LastOrDefaultI[I, S, T, A, RET, RW, DIR, ERR any](o Optic[I, S, T, A, A, RET, RW, DIR, ERR], defaultIndex I, defaultVal A) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, ERR]

func LastOrError

func LastOrError[I, S, A, RET, RW, DIR, ERR any](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], err error) Optic[I, S, S, A, A, ReturnOne, RW, UniDir, Err]

The LastOrError combinator returns an optic that focuses the last focused element or returns the given error if no elements are focused. See:

func Left

func Left[A, B any]() Optic[ChosenSide, mo.Either[A, B], mo.Either[A, B], A, A, ReturnMany, ReadWrite, BiDir, Pure]

Left returns a Prism that matches on the left element of a mo.Either

Example
left, matched := MustGetFirst(Left[int, int](), mo.Left[int, int](1))
fmt.Println(left, matched)

right, matched := MustGetFirst(Left[int, int](), mo.Right[int, int](1))
fmt.Println(right, matched)

//Setting Left on a Right value returns the original Left value
setLeft := MustSet(Left[int, int](), 2, mo.Right[int, int](1))
fmt.Println(setLeft)
Output:

1 true
0 false
{false 0 1}

func LeftP

func LeftP[A, B, C any]() Optic[ChosenSide, mo.Either[A, B], mo.Either[C, B], A, C, ReturnMany, ReadWrite, BiDir, Pure]
Example
left, matched := MustGetFirst(LeftP[int, int, string](), mo.Left[int, int](1))
fmt.Println(left, matched)

right, matched := MustGetFirst(Left[int, int](), mo.Right[int, int](1))
fmt.Println(right, matched)

var setLeft mo.Either[string, int] = MustModify(
	LeftP[int, int, string](),
	FormatInt[int](10),
	mo.Left[int, int](1),
)
fmt.Println(setLeft)
Output:

1 true
0 false
{true 1 0}

func Length

func Length[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[Void, S, S, int, int, ReturnOne, ReadOnly, UniDir, ERR]

The Length combinator returns an optic that focuses the number of elements in the given optic.

Warning: using a modify action on the return optic will return an error.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

strLenGt4 := Compose(Length(TraverseString()), Gt(4))

filteredResult := MustGet(SliceOf(Filtered(TraverseSlice[string](), strLenGt4), len(data)), data)
fmt.Println(filteredResult)

overResult := MustModify(Filtered(TraverseSlice[string](), strLenGt4), Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[alpha gamma delta]
[ALPHA beta GAMMA DELTA]

func Lens

func Lens[S, A any](
	get func(source S) A,
	set func(focus A, source S) S,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

A lens is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr: should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.
Example
//This lens focuses on the B element of a tuple
tupleB := Lens[lo.Tuple2[int, int], int](
	func(source lo.Tuple2[int, int]) int {
		return source.B
	},
	func(focus int, source lo.Tuple2[int, int]) lo.Tuple2[int, int] {
		source.B = focus
		return source
	},
	ExprCustom("ExampleLens"),
)

var viewResult int = MustGet(tupleB, lo.T2(10, 20))
fmt.Println(viewResult)

var overResult lo.Tuple2[int, int] = MustModify(tupleB, Mul(2), lo.T2(10, 20))
fmt.Println(overResult)
Output:

20
{10 40}

func LensE

func LensE[S, A any](
	get func(ctx context.Context, source S) (A, error),
	set func(ctx context.Context, focus A, source S) (S, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

A lens is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr: should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.
Example
//This lens focuses on the B element of a string tuple and converts it to an int
//reporting the error in case of conversion failure
tupleB := LensE[lo.Tuple2[string, string], int](
	func(ctx context.Context, source lo.Tuple2[string, string]) (int, error) {
		intFocus, err := strconv.ParseInt(source.B, 10, 32)
		return int(intFocus), err
	},
	func(ctx context.Context, focus int, source lo.Tuple2[string, string]) (lo.Tuple2[string, string], error) {
		source.B = strconv.Itoa(focus)
		return source, nil
	},
	ExprCustom("ExampleLensR"),
)

//Note the result is an int even though the tuple element is a string.
var viewResult int
viewResult, err := Get(tupleB, lo.T2("10", "20"))
fmt.Println(viewResult, err)

//Note the result is lo.Tuple[string,string] but the Mul operation acts on the focused int.
var overResult lo.Tuple2[string, string]
overResult, err = Modify(tupleB, Mul[int](2), lo.T2("10", "20"))
fmt.Println(overResult, err)

_, err = Modify(tupleB, Mul(2), lo.T2("10", "twenty"))
fmt.Println(err.Error())
Output:

20 <nil>
{10 40} <nil>
strconv.ParseInt: parsing "twenty": invalid syntax
optic error path:
	Custom(ExampleLensR)

func LensEP

func LensEP[S, T, A, B any](
	get func(ctx context.Context, source S) (A, error),
	set func(ctx context.Context, focus B, source S) (T, error),
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

A lens is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr: should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.

func LensI

func LensI[I, S, A any](
	get func(source S) (I, A),
	set func(focus A, source S) S,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

An indexed lens is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.
Example
//This lens focuses on the B element of a tuple with an index
tupleB := LensI[int, lo.Tuple2[int, int], int](
	func(source lo.Tuple2[int, int]) (int, int) {
		return 1, source.B
	},
	func(focus int, source lo.Tuple2[int, int]) lo.Tuple2[int, int] {
		source.B = focus
		return source
	},
	func(indexA, indexB int) bool {
		return indexA == indexB
	},
	ExprCustom("ExampleLensI"),
)

var viewIndex, viewResult int = MustGetI(tupleB, lo.T2(10, 20))
fmt.Println(viewIndex, viewResult)

var overResult lo.Tuple2[int, int] = MustModifyI(tupleB, OpI(func(index int, focus int) int {
	return index + focus
}), lo.T2(10, 20))
fmt.Println(overResult)
Output:

1 20
{10 21}

func LensIE

func LensIE[I, S, A any](
	get func(ctx context.Context, source S) (I, A, error),
	set func(ctx context.Context, focus A, source S) (S, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

An indexed lens is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.

func LensIEP

func LensIEP[I any, S, T, A, B any](
	get func(ctx context.Context, source S) (I, A, error),
	set func(ctx context.Context, focus B, source S) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

An indexed lens is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.
Example
//This lens converts the b elements of a string tuple to an int, reporting any conversion errors encountered.
//It is polymorphic so is able to return an int tuple even through the source type is a string string
parseInt := CombiLens[ReadWrite, Err, int, lo.Tuple2[string, string], lo.Tuple2[string, int], int, int](
	func(ctx context.Context, source lo.Tuple2[string, string]) (int, int, error) {
		intFocus, err := strconv.ParseInt(source.B, 10, 32)
		return 1, int(intFocus), err
	},
	func(ctx context.Context, focus int, source lo.Tuple2[string, string]) (lo.Tuple2[string, int], error) {
		return lo.T2(source.A, focus), nil
	},
	IxMatchComparable[int](),
	ExprCustom("ExampleLensF"),
)

var result lo.Tuple2[string, int]
result, err := Modify(parseInt, Mul(10), lo.T2("alpha", "10"))

fmt.Println(result, err)

_, err = Modify(parseInt, Mul(10), lo.T2("alpha", "ten"))

fmt.Println(err.Error())
Output:

{alpha 100} <nil>
strconv.ParseInt: parsing "ten": invalid syntax
optic error path:
	Custom(ExampleLensF)

func LensIP

func LensIP[I, S, T, A, B any](
	get func(source S) (I, A),
	set func(focus B, source S) T,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

An indexed lens is constructed from 4 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • ixMatch : should return true if the 2 index values are equal
  • expr : should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.

func LensP

func LensP[S, T, A, B any](
	get func(source S) A,
	set func(focus B, source S) T,
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Pure]

Constructor for a Lens optic. Lenses focus on a single element.

The following Lens constructors are available.

A lens is constructed from 3 functions

  • get : should return the single value focused by the lens
  • set : should return a new result type with the new given focused value.
  • expr: should return the expression type. See the expr package for more information.

See:

  • GetModIEP for a lens like optic that uses a modify function instead of a setter.
Example
//This lens is polymorphic. It converts the B element of a tuple from int to float64s.
intToFloat := LensP[lo.Tuple2[string, int], lo.Tuple2[string, float64], int, float64](
	func(source lo.Tuple2[string, int]) int {
		return source.B
	},
	func(focus float64, source lo.Tuple2[string, int]) lo.Tuple2[string, float64] {
		return lo.T2(source.A, focus)
	},
	ExprCustom("ExampleLensP"),
)

var result lo.Tuple2[string, float64] = MustModify(intToFloat, Op(func(focus int) float64 {
	return float64(focus) + 0.5
}), lo.T2("alpha", 10))

fmt.Println(result)
Output:

{alpha 10.5}

func Lined

Lined returns a Traversal over the line feed separated lines in the source string.

Example
numLines := MustGet(Length(Lined()), "Lorem Ipsum\n\nDolor\nSit Amet")
fmt.Println(numLines)

result := MustModifyI(Lined(), OpI(func(index int, word string) string {
	if index%2 == 0 {
		return strings.ToUpper(word) //Convert even indexed lines to uppercase
	} else {
		return strings.ToLower(word) //Convert odd indexed lines to lowercase
	}

}), "Lorem Ipsum\n\nDolor\nSit Amet")
fmt.Println(result)
Output:

3
LOREM IPSUM

dolor
SIT AMET

func Lookup

func Lookup[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], source S) Optic[I, I, I, mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, ERR]

The Lookup combinator returns an optic that focuses on the indexed element within the given optic and source.

See:

  • Index for a version that looks up a fixed index.
Example
vowels := map[rune]bool{
	'a': true,
	'e': true,
	'i': true,
	'o': true,
	'u': true,
}

inVowels := Compose(Lookup(TraverseMap[rune, bool](), vowels), Non(false, EqT2[bool]()))

index, vowel, found := MustGetFirstI(Filtered(TraverseString(), inVowels), "hello world")
fmt.Println(index, string(vowel), found)
Output:

1 e true

func Lt

func Lt[A cmp.Ordered](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Lt returns a Predicate that is satisfied if the focused value is less than (<) the provided constant value.

See:

  • LtOp for a Predicate that compares 2 focuses instead of a constant.
  • LtI for a version that compares indices.
Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(SliceOf(Filtered(TraverseSlice[int](), Lt(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Lt(3), data)
fmt.Println(overResult)
Output:

[1 2]
[true true false false false]

func LtI

func LtI[A any, P cmp.Ordered](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

IL returns a PredicateI that is satisfied if the focused index is less than (<) the provided constant value.

See:

  • Gt for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, LtI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[alpha beta]

func LtOp

func LtOp[S any, A cmp.Ordered, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

LtOp returns a Predicate that is satisfied if the left focus is less (<) the right focus.

See:

  • Lt for a predicate that checks constant a value rather than 2 focuses.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A<B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := LtOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{1 2}]
[false true false false]

func LtT2

func LtT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

LtT2 returns an BinaryOp that is satisfied if A < B.

See:

  • Lt for a unary version.
  • LtOp for a version that is applied to the focus of 2 [Operation]s.

func Lte

func Lte[A cmp.Ordered](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Lte returns a Predicate that is satisfied if the focused value is less than or equal to (<=) the provided constant value.

See:

  • LteOp for a Predicate that compares 2 focuses instead of a constant.
  • LteI for a version that compares indices.
Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(SliceOf(Filtered(TraverseSlice[int](), Lte(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Lte(3), data)
fmt.Println(overResult)
Output:

[1 2 3]
[true true true false false]

func LteI

func LteI[A any, P cmp.Ordered](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

LteI returns a PredicateI that is satisfied if the focused index is less than or equal to than (<=) the provided constant value.

See:

  • Lte for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, LteI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[alpha beta gamma]

func LteOp

func LteOp[S any, A cmp.Ordered, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

LteOp returns a Predicate that is satisfied if the left focus is less than or equal to (<=) the right focus.

See Lte for a predicate that checks constant a value rather than 2 focuses.

Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A<=B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := LteOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{1 1} {1 2} {2 2}]
[true true false true]

func LteT2

func LteT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

LteT2 returns an BinaryOp that is satisfied if A <= B.

See:

  • Lte for a unary version.
  • LteOp for a version that is applied to the focus of 2 [Operation]s.

func MakeMap

func MakeMap[S any, K comparable, V any](size int) Optic[Void, S, S, map[K]V, map[K]V, ReturnOne, ReadOnly, UniDir, Pure]

func MakeSlice

func MakeSlice[S any, V any](size, cap int) Optic[Void, S, S, []V, []V, ReturnOne, ReadOnly, UniDir, Pure]

func MapOf

func MapOf[I comparable, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], size int) Optic[Void, S, T, map[I]A, map[I]A, ReturnOne, RW, UniDir, Err]

The MapOf combinator focuses on a map of all the elements in the given optic. If multiple focuses have the same index a ErrDuplicateKey is returned

Under modification this map can be modified using standard operations and will be rebuilt into the original data structure. If the modified map does not contain a key that is present in the source the result will use values from the original source. If the modified map contains additional keys they will be ignored.

See:

  • MapOfP for a polymorphic version.
Example
data := []string{
	"alpha",
	"beta",
	"gamma",
	"delta",
}

optic := MapOf(TraverseSlice[string](), len(data))

var viewResult map[int]string
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

var modifyResult []string
modifyResult, err = Modify(optic, Op(func(focus map[int]string) map[int]string {
	focus[1] = "beta-test"
	return focus
}), data)
fmt.Println(modifyResult, err)
Output:

map[0:alpha 1:beta 2:gamma 3:delta] <nil>
[alpha beta-test gamma delta] <nil>

func MapOfP

func MapOfP[I comparable, S, T, A, B, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR], size int) Optic[Void, S, T, map[I]A, map[I]B, ReturnOne, RW, UniDir, Err]

The MapOfP combinator focuses on a polymorphic map of all the elements in the given optic. If multiple focuses have the same index a ErrDuplicateKey is returned

Under modification this map can be modified using standard operations and will be rebuilt into the original data structure. If the modified map does not contain a key that is present in the source then ErrUnsafeMissingElement will be returned If the modified map contains additional keys they will be ignored.

See:

  • MapOf for a safe non polymorphic version.
Example
data := []string{
	"1",
	"2",
	"3",
	"4",
}

optic := MapOfP(TraverseSliceP[string, int](), len(data))

var viewResult map[int]string
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

var modifyResult []int
modifyResult, err = Modify(optic, Op(func(focus map[int]string) map[int]int {
	ret := make(map[int]int)

	for k, v := range focus {
		intVal, _ := strconv.ParseInt(v, 10, 32)
		ret[k] = int(intVal*10) + k
	}

	return ret
}), data)
fmt.Println(modifyResult, err)
Output:

map[0:1 1:2 2:3 3:4] <nil>
[10 21 32 43] <nil>

func MapOfReduced

func MapOfReduced[I comparable, S, T, A, RETI, RW, DIR, ERR, SR, RERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], r ReductionP[SR, A, A, RERR], size int) Optic[Void, S, T, map[I]A, map[I]A, ReturnOne, RW, UniDir, CompositionTree[ERR, RERR]]

The MapOfReduced combinator focuses on a map of all the elements in the given optic. If multiple focuses have the same index the last focused value is used.

Under modification this map can be modified using standard operations and will be rebuilt into the original data structure. If the modified map does not contain a key that is present in the source the result will use values from the original source. If the modified map contains additional keys they will be ignored.

See:

Example
data := ValColI(
	IxMatchComparable[string](),
	ValI("alpha", 1),
	ValI("beta", 2),
	ValI("alpha", 3),
)

optic := MapOfReduced(TraverseCol[string, int](), FirstReducer[int](), 3)

var viewResult map[string]int
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

var modifyResult Collection[string, int, Pure]
modifyResult, err = Modify(optic, Op(func(focus map[string]int) map[string]int {
	focus["beta"] = 10
	return focus
}), data)
fmt.Println(modifyResult, err)
Output:

map[alpha:1 beta:2] <nil>
Col[alpha:1 beta:10 alpha:1] <nil>

func MapOfReducedP

func MapOfReducedP[I comparable, S, T, A, B, RETI, RW, DIR, ERR, SR, RERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR], r ReductionP[SR, A, A, RERR], size int) Optic[Void, S, T, map[I]A, map[I]B, ReturnOne, RW, UniDir, Err]

The MapOfReducedP combinator focuses on a map of all the elements in the given optic. If multiple focuses have the same index the last focused value is used.

Under modification this map can be modified using standard operations and will be rebuilt into the original data structure. If the modified map does not contain a key that is present in the source then a ErrUnsafeMissingElement will be returned If the modified map contains additional keys they will be ignored.

See:

  • MapOfReduced for a non polymorphic version.
  • MapOfP for a version that uses the first focus.
Example
data := ValColI(
	IxMatchComparable[string](),
	ValI("alpha", 1),
	ValI("beta", 2),
	ValI("alpha", 3),
)

optic := MapOfReducedP(TraverseColP[string, int, string](), FirstReducer[int](), 3)

var viewResult map[string]int
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

var modifyResult Collection[string, string, Pure]
modifyResult, err = Modify(optic, Op(func(focus map[string]int) map[string]string {
	ret := make(map[string]string)

	for k, v := range focus {
		strVal := strconv.Itoa(v)
		ret[k] = strVal
	}

	return ret
}), data)
fmt.Println(modifyResult, err)
Output:

map[alpha:1 beta:2] <nil>
Col[alpha:1 beta:2 alpha:1] <nil>

func MapOp

func MapOp[K comparable, S, T any, I any, RET TReturnOne, RW any, DIR, ERR any](o Optic[I, Collection[K, S, ERR], Collection[K, T, ERR], Collection[K, T, ERR], Collection[K, T, ERR], RET, RW, DIR, ERR]) Optic[I, map[K]S, map[K]T, map[K]T, map[K]T, ReturnOne, RW, DIR, ERR]

The MapOp combinator applies the given collection operation to a Map and focuses the modified Map.

See:

  • [MapTraverseOp] for a combinator that efficiently traverses the elements of the modified Map.
  • [MapColOp] for a combinator that focuses the modified Collection.
Example
data := lo.T2(
	1,
	map[int]string{
		1: "alpha",
		2: "beta",
		3: "gamma",
		4: "delta",
	},
)

optic := MapOp(
	FilteredCol[int](Ne("beta")),
)

var getRes map[int]string = MustGet(
	Compose(
		T2B[int, map[int]string](),
		optic,
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, map[int]string] = MustModify(
	T2B[int, map[int]string](),
	optic,
	data,
)
fmt.Println(modifyRes)
Output:

map[1:alpha 3:gamma 4:delta]
{1 map[1:alpha 3:gamma 4:delta]}

func MapReduce

func MapReduce[I, S, T, A, B, RET, RW, DIR, ERR, SM, M, RM, ERRMAP, ERRREDUCE any, MRET TReturnOne](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], mapper Operation[A, M, MRET, ERRMAP], m ReductionP[SM, M, RM, ERRREDUCE]) Optic[Void, S, S, RM, RM, RET, ReadOnly, UniDir, CompositionTree[CompositionTree[ERR, ERRREDUCE], ERRMAP]]

The MapReduce combinator returns an Iteration that focuses the result of applying the Reducer to the given optic after applying the mapper operator.

Example
data := []string{"1", "2", "3", "4"}

sum, ok, err := GetFirst(MapReduce(TraverseSlice[string](), ParseInt[int](10, 32), Sum[int]()), data)

fmt.Println(sum, ok, err)
Output:

10 true <nil>

func MapToCol

func MapToCol[K comparable, A any]() Optic[Void, map[K]A, map[K]A, Collection[K, A, Pure], Collection[K, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

MapToCol returns an Iso that converts a map to an Collection

Note: In the case of duplicate indices ReverseGet will use the last occurrence.

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

var getRes map[int]string = MustGet(
	Compose3(
		MapToCol[int, string](),
		FilteredCol[int](Ne("beta")),
		AsReverseGet(MapToCol[int, string]()),
	),
	data,
)
fmt.Println(getRes)

var modifyRes map[int]string = MustModify(
	MapToCol[int, string](),
	FilteredCol[int](Ne("beta")),
	data,
)
fmt.Println(modifyRes)
Output:

map[1:alpha 3:gamma 4:delta]
map[1:alpha 3:gamma 4:delta]

func MapToColP

func MapToColP[I comparable, A, B any]() Optic[Void, map[I]A, map[I]B, Collection[I, A, Pure], Collection[I, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

MapToColP returns a polymorphic Iso that converts a map to an Collection

Note: In the case of duplicate indices ReverseGet will use the last occurrence.

func MatchIndexCaptures

func MatchIndexCaptures() Optic[Void, MatchIndex, MatchIndex, []string, []string, ReturnOne, ReadWrite, UniDir, Pure]

MatchIndexOffsets returns a Lens that focuses the Captures field of a MatchIndex

See:

func MatchIndexOffsets

func MatchIndexOffsets() Optic[Void, MatchIndex, MatchIndex, []int, []int, ReturnOne, ReadWrite, UniDir, Pure]

MatchIndexOffsets returns a Lens that focuses the Offsets field of a MatchIndex

See:

func MatchString

MatchString returns an Traversal that focuses on the n substrings that match the given regexp.

Use an n value of -1 to match all the focuses. The index provides access to the capture group offsets and their values

See:

  • CaptureString for a for Traversal that focuses on the indexed capture groups within a regexp..
  • CaptureMapString for a for Traversal that focuses on the named capture groups within a regexp..
  • SplitString for a for Traversal that splits strings based on a regexp.
Example
data := "Lorem 10 ipsum 20 dolor"

var sliceResult []string = MustGet(
	SliceOf(
		MatchString(
			regexp.MustCompile(`\d+`),
			-1,
		),
		10,
	),
	data,
)
fmt.Println(sliceResult)

var overResult string
overResult, err := Modify(
	Compose(
		MatchString(
			regexp.MustCompile(`\d+`),
			-1,
		),
		ParseInt[int](10, 32)),
	Mul(2),
	data,
)
fmt.Println(overResult, err)
Output:

[10 20]
Lorem 20 ipsum 40 dolor <nil>

func Matching

func Matching[I, S, T, A, B, RET any, RW TReadWrite, DIR TBiDir, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, S, mo.Either[T, A], mo.Either[T, A], ReturnOne, ReadOnly, UniDir, ERR]

The Matching combinator returns an optic that focuses on either the matching value of the given Prism or the source transformed to the result type.

Example
var result mo.Either[any, string] = MustGet(
	Matching(
		DownCast[any, string](),
	),
	"alpha",
)
fmt.Println(result.MustRight()) //The cast matches so we get the cast value on the right

result = MustGet(
	Matching(
		DownCast[any, string](),
	),
	1.2,
)
fmt.Println(result.MustLeft()) //The cast does not match so we get the original value on the left
Output:

alpha
1.2

func Max

func Max[A cmp.Ordered](right A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Max returns an Operation that returns the maximum value

See:

  • MaxOp for a version that is applied to the focus of 2 [Operation]s.
  • MaxReducer for a Reducer variant.
  • [MaxI] for a version that also returns the index.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 1),
	lo.T2("b", 2),
	lo.T2("c", 3),
	lo.T2("d", 4),
	lo.T2("e", 5),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Update each element so the value is 3 or greater
var overResult []lo.Tuple2[string, int] = MustModify(optic, Max(3), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition applies a maximum of 3 then adds 1
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Max(3), Add(1)), data)
fmt.Println(composedResult)
Output:

[{a 3} {b 3} {c 3} {d 4} {e 5}]
[{a 4} {b 4} {c 4} {d 5} {e 6}]

func MaxOf

func MaxOf[C cmp.Ordered, I, S, T, A any, RETI any, RETJ TReturnOne, RWI, DIRI any, ERR, ERRCMP any](o Optic[I, S, T, A, A, RETI, RWI, DIRI, ERR], cmpBy Operation[A, C, RETJ, ERRCMP]) Optic[I, S, T, A, A, RETI, RWI, UniDir, CompositionTree[ERR, ERRCMP]]

The MaxOf combinator returns an optic that focuses the element with the maximum value as focused by the cmpBy optic

Example
data := []lo.Tuple2[string, int]{
	lo.T2("alpha", 1),
	lo.T2("beta", 2),
	lo.T2("gamma", 30),
	lo.T2("delta", 4),
}

optic := TraverseSlice[lo.Tuple2[string, int]]()
cmp := T2B[string, int]()

var index int
var maxTuple lo.Tuple2[string, int]
var ok bool
index, maxTuple, ok = MustGetFirstI(MaxOf(optic, cmp), data)

fmt.Println(index, maxTuple, ok)

var overResult []lo.Tuple2[string, int] = MustModify(Compose(MaxOf(optic, cmp), T2B[string, int]()), Mul(10), data)
fmt.Println(overResult)
Output:

2 {gamma 30} true
[{alpha 1} {beta 2} {gamma 300} {delta 4}]

func MaxOp

func MaxOp[S any, A cmp.Ordered, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

MaxOp returns an Operation expression that returns the maximum of the values focused by 2 [Operation]s.

See:

  • Max for the constant version.
  • MaxReducer for a Reducer variant.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 6),
	lo.T2(7, 2),
	lo.T2(3, 8),
	lo.T2(9, 4),
	lo.T2(5, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Mul function to the focuses of both optics
minimum := MaxOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(minimum, lo.T2(2, 10))
fmt.Println(singleValueResult) // 10

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), minimum, data)
fmt.Println(overResult) // [6 7 8 9 10]
Output:

10
[6 7 8 9 10]

func MaxT2

func MaxT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

MaxT2 returns an BinaryOp that returns the maximum.

See:

  • Max for a unary version.
  • MaxOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []int{5, 2}

//returns a reducer that takes the max of all the numbers in a slice
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(math.MinInt, MaxT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

5 true

func MethodGetter

func MethodGetter[S, A any](fref func(S) A) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]
Example
data, _ := os.Stat(".")

optic := MethodGetter(fs.FileInfo.Name)

name := MustGet(optic, data)
fmt.Println(name)
Output:

.

func MethodGetterContext

func MethodGetterContext[S, A any](fref func(S, context.Context) (A, error)) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

func MethodGetterE

func MethodGetterE[S, A any](fref func(S) (A, error)) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

func MethodGetterI

func MethodGetterI[I, S, A any](fref func(S) (I, A), ixMatch func(indexA, indexB I) bool) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

func MethodGetterIE

func MethodGetterIE[I, S, A any](fref func(S, context.Context) (I, A, error), ixMatch func(indexA, indexB I) bool) Optic[I, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

func MethodLens

func MethodLens[S, A any](get func(S) A, set func(S, A) S) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

func MethodLensContext

func MethodLensContext[S, A any](get func(S, context.Context) (A, error), set func(S, context.Context, A) (S, error)) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

func MethodLensE

func MethodLensE[S, A any](get func(S) (A, error), set func(S, A) (S, error)) Optic[Void, S, S, A, A, ReturnOne, ReadWrite, UniDir, Err]

func MethodLensI

func MethodLensI[I, S, A any](get func(S) (I, A), set func(S, A) S, ixMatch func(indexA, indexB I) bool) Optic[I, S, S, A, A, ReturnOne, ReadWrite, UniDir, Pure]

func MethodLensIEP

func MethodLensIEP[I, S, T, A, B any](get func(S, context.Context) (I, A, error), set func(S, context.Context, B) (T, error), ixMatch func(indexA, indexB I) bool) Optic[I, S, T, A, B, ReturnOne, ReadWrite, UniDir, Err]

func MethodLensP

func MethodLensP[S, T, A, B any](get func(S) A, set func(S, B) T) Optic[Void, S, T, A, B, ReturnOne, ReadWrite, UniDir, Pure]

func Min

func Min[A cmp.Ordered](right A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Min returns an Operation that returns the minimum value

See:

  • MinOp for a version that is applied to the focus of 2 [Operation]s.
  • MinReducer for a Reducer variant.
  • [MinI] for a version that returns also return the index.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 1),
	lo.T2("b", 2),
	lo.T2("c", 3),
	lo.T2("d", 4),
	lo.T2("e", 5),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Update each element so the value is 3 or less
var overResult []lo.Tuple2[string, int] = MustModify(optic, Min(3), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition applies a minimum of 3 then adds 1
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Min(3), Add(1)), data)
fmt.Println(composedResult)
Output:

[{a 1} {b 2} {c 3} {d 3} {e 3}]
[{a 2} {b 3} {c 4} {d 4} {e 4}]

func MinOf

func MinOf[C cmp.Ordered, I, S, T, A any, RETI any, RETJ TReturnOne, RWI, DIRI any, ERR, ERRCMP any](o Optic[I, S, T, A, A, RETI, RWI, DIRI, ERR], cmpBy Operation[A, C, RETJ, ERRCMP]) Optic[I, S, T, A, A, RETI, RWI, UniDir, CompositionTree[ERR, ERRCMP]]

The MinOf combinator returns an optic that focuses the element with the minimum value as focused by the cmpBy optic

Example
data := []lo.Tuple2[string, int]{
	lo.T2("alpha", 10),
	lo.T2("beta", 20),
	lo.T2("gamma", 3),
	lo.T2("delta", 40),
}

optic := TraverseSlice[lo.Tuple2[string, int]]()
cmp := T2B[string, int]()

var index int
var minTuple lo.Tuple2[string, int]
var ok bool
index, minTuple, ok = MustGetFirstI(MinOf(optic, cmp), data)

fmt.Println(index, minTuple, ok)

var overResult []lo.Tuple2[string, int] = MustModify(Compose(MinOf(optic, cmp), T2B[string, int]()), Mul(10), data)
fmt.Println(overResult)
Output:

2 {gamma 3} true
[{alpha 10} {beta 20} {gamma 30} {delta 40}]

func MinOp

func MinOp[S any, A cmp.Ordered, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

MinOp returns an Operation expression that returns the minimum of the 2 [Operation]s.

See:

  • Min for the constant version.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 6),
	lo.T2(7, 2),
	lo.T2(3, 8),
	lo.T2(9, 4),
	lo.T2(5, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Mul function to the focuses of both optics
minimum := MinOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(minimum, lo.T2(2, 10))
fmt.Println(singleValueResult) // 2

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), minimum, data)
fmt.Println(overResult) // [1 2 3 4 5]
Output:

2
[1 2 3 4 5]

func MinT2

func MinT2[A cmp.Ordered]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

MinT2 returns an BinaryOp that returns the minimum.

See:

  • Min for a unary version.
  • MinOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []int{5, 2}

//returns a reducer that takes the min of all the numbers in a slice
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(math.MaxInt, MinT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

2 true

func Mod

func Mod[A Integer](right A) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Mod returns a Iso that performs a modulo by a constant value.

See:

  • ModT2 for the BinaryOp version
  • ModOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 10),
	lo.T2("b", 21),
	lo.T2("c", 32),
	lo.T2("d", 43),
	lo.T2("e", 55),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Perform modulo 10 on each focused int.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Mod(10), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition performs Modulo 10 then adds 10
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Mod(10), Add(10)), data)
fmt.Println(composedResult)
Output:

[{a 0} {b 1} {c 2} {d 3} {e 5}]
[{a 10} {b 11} {c 12} {d 13} {e 15}]

func ModOp

func ModOp[S any, A Integer, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

ModOp returns an Operation expression that applies a modulo to the focuses of 2 [Operation]s.

See:

Example
data := []lo.Tuple2[int, int]{
	lo.T2(10, 6),
	lo.T2(20, 7),
	lo.T2(30, 8),
	lo.T2(40, 9),
	lo.T2(50, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Mod function to the focuses of both optics
moder := ModOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(moder, lo.T2(20, 7))
fmt.Println(singleValueResult) // 6

//The created getter is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), moder, data)
fmt.Println(overResult) // [4 6 6 4 0]
Output:

6
[4 6 6 4 0]

func ModT2

func ModT2[A Integer]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

ModT2 returns an BinaryOp that applies A % B.

See:

  • Mod for a unary version.
  • ModOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(5, 2),
	lo.T2(6, 2),
	lo.T2(5, 3),
	lo.T2(6, 3),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[int, int]](),
	ModT2[int](),
)

var res []int = MustGet(
	SliceOf(
		optic,
		4,
	),
	data,
)
fmt.Println(res)
Output:

[1 0 2 0]

func Mul

func Mul[A Arithmetic](right A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Mul returns an Iso that multiplies by a constant value.

See:

  • MulT2 for the BinaryOp version.
  • MulOp for a version that is applied to the focus of 2 [Operation]s.
  • Product for a Reducer variant.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 1),
	lo.T2("b", 2),
	lo.T2("c", 3),
	lo.T2("d", 4),
	lo.T2("e", 5),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Multiply each focused int by 10.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Mul(10), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition multiples by 10 then adds 1
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Mul(10), Add(1)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a multipleied by 10 context
//But when the result is built the value is divided by 10 again to return it to the original context
//In effect the Add(100) is in effect an Add(10)
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Mul(10)), Add(100), data)
fmt.Println(preComposedResult)
Output:

[{a 10} {b 20} {c 30} {d 40} {e 50}]
[{a 11} {b 21} {c 31} {d 41} {e 51}]
[{a 11} {b 12} {c 13} {d 14} {e 15}]

func MulOp

func MulOp[S any, A Arithmetic, RETL, RETR TReturnOne, ERRL, ERRR any](left Operation[S, A, RETL, ERRL], right Operation[S, A, RETR, ERRR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[ERRL, ERRR]]

MulOp returns an Operation expression that multiplies the focuses of 2 [Operation]s.

See:

Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 6),
	lo.T2(2, 7),
	lo.T2(3, 8),
	lo.T2(4, 9),
	lo.T2(5, 10),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Mul function to the focuses of both optics
multiplier := MulOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(multiplier, lo.T2(2, 10))
fmt.Println(singleValueResult) // 20

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), multiplier, data)
fmt.Println(overResult) // [6 14 24 36 50]
Output:

20
[6 14 24 36 50]

func MulT2

func MulT2[A Arithmetic]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

MulT2 returns an BinaryOp that multiplies 2 values.

See:

  • Mul for a unary version.
  • MulOp for a version that is applied to the focus of 2 [Operation]s.
  • Product for a Reducer variant.
Example
data := []int{1, 2, 3, 4}

//returns a reducer that multiplies all the numbers in a slice
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(1, MulT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

24 true

func Ne

func Ne[A comparable](right A) Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Ne returns a Predicate that is satisfied if the focused value is not equal to (!=) the provided value.

See:

  • NeOp for a Predicate that compares 2 focuses instead of a constant.
  • NeI for a version that compares indices.
Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(SliceOf(Filtered(TraverseSlice[int](), Ne(3)), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), Ne(3), data)
fmt.Println(overResult)
Output:

[1 2 4 5]
[true true false true true]

func NeI

func NeI[A any, P comparable](right P) Optic[Void, ValueI[P, A], ValueI[P, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

NeI returns a PredicateI that is satisfied if the focused index is not equal to (!=) the provided constant value.

See:

  • Ne for a version that compares the focused value and not the index.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice
optic := TraverseSlice[string]()

var result []string
result = MustGet(
	SliceOf(
		FilteredI(

			optic, NeI[string](2),
		),
		len(data),
	),
	data,
)
fmt.Println(result)
Output:

[alpha beta delta]

func NeOp

func NeOp[S any, A comparable, RETL, RETR TReturnOne, LERR, RERR any](left Operation[S, A, RETL, LERR], right Operation[S, A, RETR, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

NeOp returns a Predicate that is satisfied if the left focus is not equal to (!=) the right focus.

See Ne for a predicate that checks constant a value rather than 2 focuses.

Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
}

//returns a predicate that matches if A!=B in the tuple
//the type of this predicate is equivalent to func(lo.Tuple2[int,int])bool
predicate := NeOp(T2A[int, int](), T2B[int, int]())

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicate)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

var overResult []bool = Must(Modify(TraverseSliceP[lo.Tuple2[int, int], bool](), predicate, data))
fmt.Println(overResult)
Output:

[{1 2} {2 1}]
[false true true false]

func NeT2

func NeT2[A comparable]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

NeT2 returns an BinaryOp that is satisfied if A != B.

See:

  • [NE] for a unary version.
  • NeOp for a version that is applied to the focus of 2 [Operation]s.

func Negate

func Negate[A Arithmetic]() Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Negate returns a Iso that negates the value.

Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 11),
	lo.T2("b", 22),
	lo.T2("c", 33),
	lo.T2("d", 44),
	lo.T2("e", 55),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Negate each focused int.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Negate[int](), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition negates then Adds 2
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Negate[int](), Add(2)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a negated context
//But when the result is built the value is negated again to return it to the original context.
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Negate[int]()), Add(2), data)
fmt.Println(preComposedResult)
Output:

[{a -11} {b -22} {c -33} {d -44} {e -55}]
[{a -9} {b -20} {c -31} {d -42} {e -53}]
[{a 9} {b 20} {c 31} {d 42} {e 53}]

func Non

func Non[A, ERR any](defaultValue A, equal Predicate[lo.Tuple2[A, A], ERR]) Optic[Void, mo.Option[A], mo.Option[A], A, A, ReturnOne, ReadWrite, BiDir, ERR]

Non returns an Iso that converts a None value of a mo.Option to the given default value.

Warning: this has the effect that under modification the default value is converted to a None mo.Option value.

  • See Some for an optic that filters out None values.
  • See None for an optic that filters out Some values.
Example
data := []mo.Option[int]{
	mo.Some(1),
	mo.None[int](),
	mo.Some(2),
}

//View actions like MustListOf convert the none elements to the default value
var results []int = MustGet(SliceOf(Compose(TraverseSlice[mo.Option[int]](), Non[int](-1, EqT2[int]())), len(data)), data)
fmt.Println(results)

//Unlike Some and None we now have default value we can operate on.
var overResult []mo.Option[int] = MustModify(Compose(TraverseSlice[mo.Option[int]](), Non[int](-1, EqT2[int]())), Mul(10), data)
fmt.Println(overResult)

//Warning: setting the value to the default value will cause it to be represented as the None value in the result.
var setDefaultResult []mo.Option[int] = MustSet(Compose(TraverseSlice[mo.Option[int]](), Non[int](-1, EqT2[int]())), -1, data)
fmt.Println(setDefaultResult)
Output:

[1 -1 2]
[{true 10} {true -10} {true 20}]
[{false 0} {false 0} {false 0}]

func None

func None[A any]() Optic[Void, mo.Option[A], mo.Option[A], Void, Void, ReturnMany, ReadWrite, BiDir, Pure]

None returns a Prism that matches on the None state of a mo.Option. A void focus type is returned as the none value has no valid representation.

See:

  • Non for an optic that provides default values for None values.
  • Some for an optic that matches on Some values.
Example
data := []mo.Option[int]{
	mo.Some(1),
	mo.None[int](),
	mo.Some(2),
}

//View actions like MustView ignore the Some elements.
count := MustGet(Length(Compose(TraverseSlice[mo.Option[int]](), None[int]())), data)
fmt.Println(count)

//There are no sensible transformations of the Void type so modification actions make little sense for None.
var overResult []mo.Option[int] = MustModify(Compose(TraverseSlice[mo.Option[int]](), None[int]()), Identity[Void](), data)
fmt.Println(overResult)
Output:

1
[{true 1} {false 0} {true 2}]

func Not

Not returns a Iso that logically nots the value.

Example
data := []int{1, 2, 3, 4, 5}

notPredicate := Compose(Gt(3), Not())

var filtered []int = MustGet(SliceOf(Filtered(TraverseSlice[int](), notPredicate), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), notPredicate, data)
fmt.Println(overResult)
Output:

[1 2 3]
[true true true false false]

func NotEmpty

func NotEmpty[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

NotEmpty returns a Predicate that is satisfied if the the given optic focuses any elements.

See Empty for the inverse version.

Example
var result bool = MustGet(
	NotEmpty(TraverseSlice[string]()),
	[]string{"alpha", "beta", "gamma", "delta"},
)
fmt.Println(result)

result = MustGet(
	NotEmpty(TraverseSlice[string]()),
	[]string{},
)
fmt.Println(result)
Output:

true
false

func NotOp

func NotOp[S, ERR any](pred Predicate[S, ERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

NotOp is a combinator that applies the Not operation to a Predicate.

Example
data := []int{1, 2, 3, 4, 5}

notPredicate := NotOp(Gt(3))

var filtered []int = MustGet(SliceOf(Filtered(TraverseSlice[int](), notPredicate), len(data)), data)
fmt.Println(filtered)

var overResult []bool = MustModify(TraverseSliceP[int, bool](), notPredicate, data)
fmt.Println(overResult)
Output:

[1 2 3]
[true true true false false]

func Nothing

func Nothing[S any, A any]() Optic[Void, S, S, A, A, ReturnMany, ReadWrite, UniDir, Pure]

Nothing returns a Traversal that focuses no elements

Example
data := [][]string{
	{"alpha", "beta"},
	{"gamma"},
	{"delta", "epsilon"},
}

optic := Compose(
	TraverseSlice[[]string](),
	If(
		Compose(
			Length(
				TraverseSlice[string](),
			),
			Lt(2),
		),
		ReIndexed(Nothing[[]string, string](), Const[Void](0), EqT2[int]()),
		TraverseSlice[string](),
	),
)

res := MustGet(SliceOf(optic, 4), data)
fmt.Println(res)

modRes := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(modRes)
Output:

[alpha beta delta epsilon]
[[ALPHA BETA] [gamma] [DELTA EPSILON]]

func NothingI

func NothingI[S any, A, I any, ERR TPure](ixMatch Predicate[lo.Tuple2[I, I], ERR]) Optic[I, S, S, A, A, ReturnMany, ReadWrite, UniDir, Pure]

NothingI returns an index aware Traversal that focuses no elements

Example
data := [][]string{
	{"alpha", "beta"},
	{"gamma"},
	{"delta", "epsilon"},
}

optic := Compose(
	WithIndex(TraverseSlice[[]string]()),
	If(
		OpOnIx[[]string](Odd[int]()),
		Compose(ValueIValue[int, []string](), ReIndexed(Nothing[[]string, string](), Const[Void](0), EqT2[int]())),
		Compose(ValueIValue[int, []string](), TraverseSlice[string]()),
	),
)

res := MustGet(SliceOf(optic, 4), data)
fmt.Println(res)

modRes := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(modRes)
Output:

[alpha beta delta epsilon]
[[ALPHA BETA] [gamma] [DELTA EPSILON]]

func Odd

func Odd[A Integer]() Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Odd returns a predicate is satisfied if the given arithmetic value is odd.

func Omni

func Omni[I, S, T, A, B, RET, RW, DIR, ERR any](
	getter GetterFunc[I, S, A],
	setter SetterFunc[S, T, B],

	iter IterFunc[I, S, A],
	lengthGetter LengthGetterFunc[S],
	modify ModifyFunc[I, S, T, A, B],

	ixGetter IxGetterFunc[I, S, A],
	ixMatchFnc IxMatchFunc[I],

	reverseGetter ReverseGetterFunc[T, B],

	exprDef ExpressionDef,
) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

Omni returns an optic using the given functions with added protection for unsafe iteration functions (yield after break) and automatic generation of the OpticError path Omni optics should only be used when creating custom combinators.

Note: If the getter function is unable to return a result due to an empty iteration it MUST return an ErrEmptyGet

See:

Example
package main

import (
	"context"
	"fmt"
	"strings"

	. "github.com/spearson78/go-optic"
)

func WithExampleLogging[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR] {

	return Omni[I, S, T, A, B, RET, RW, DIR, ERR](
		func(ctx context.Context, source S) (I, A, error) {
			i, a, err := o.AsGetter()(ctx, source)
			fmt.Println("Get", source, i, a, err)
			return i, a, err
		},
		func(ctx context.Context, focus B, source S) (T, error) {
			t, err := o.AsSetter()(ctx, focus, source)
			fmt.Println("Set", source, t, err)
			return t, err
		},
		func(ctx context.Context, source S) SeqIE[I, A] {
			return func(yield func(val ValueIE[I, A]) bool) {
				o.AsIter()(ctx, source)(func(val ValueIE[I, A]) bool {
					index, focus, err := val.Get()
					ret := yield(ValIE(index, focus, err))
					fmt.Println("Iterate", source, index, focus, err)
					return ret
				})
			}
		},
		func(ctx context.Context, source S) (int, error) {
			l, err := o.AsLengthGetter()(ctx, source)
			fmt.Println("GetLength", source, l, err)
			return l, err

		},
		func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error) {
			t, err := o.AsModify()(ctx, func(index I, focus A) (B, error) {
				b, err := fmap(index, focus)
				fmt.Println("Modify", source, index, focus, b, err)
				return b, err
			}, source)
			return t, err
		},
		func(ctx context.Context, index I, source S) SeqIE[I, A] {
			return func(yield func(val ValueIE[I, A]) bool) {
				o.AsIxGetter()(ctx, index, source)(func(val ValueIE[I, A]) bool {
					focusIndex, focus, err := val.Get()
					ret := yield(ValIE(focusIndex, focus, err))
					fmt.Println("IxGet", source, index, focusIndex, focus, err, ret)
					return ret
				})
			}
		},
		func(indexA, indexB I) bool {
			match := o.AsIxMatch()(indexA, indexB)
			fmt.Println("IxMatch", indexA, indexB, match)
			return match
		},
		func(ctx context.Context, focus B) (T, error) {
			t, err := o.AsReverseGetter()(ctx, focus)
			fmt.Println("ReverseGet", focus, t, err)
			return t, err
		},
		ExprCustom("WithExampleLogging"),
	)
}

func main() {

	data := []string{"alpha", "beta", "gamma", "delta"}

	optic := WithExampleLogging(TraverseSlice[string]())

	result := MustGet(SliceOf(optic, len(data)), data)
	fmt.Println("Result:", result)

	result = MustModify(optic, Op(strings.ToUpper), data)
	fmt.Println("Result:", result)

}
Output:

Iterate [alpha beta gamma delta] 0 alpha <nil>
Iterate [alpha beta gamma delta] 1 beta <nil>
Iterate [alpha beta gamma delta] 2 gamma <nil>
Iterate [alpha beta gamma delta] 3 delta <nil>
Result: [alpha beta gamma delta]
Modify [alpha beta gamma delta] 0 alpha ALPHA <nil>
Modify [alpha beta gamma delta] 1 beta BETA <nil>
Modify [alpha beta gamma delta] 2 gamma GAMMA <nil>
Modify [alpha beta gamma delta] 3 delta DELTA <nil>
Result: [ALPHA BETA GAMMA DELTA]

func Op

func Op[S, A any](op func(source S) A) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [Operator] for a version that has an expression parameter.
- [Op] pure, non indexed,non polymorphic
- [OpI] pure, index aware,non polymorphic
- [OpE] impure, non indexed,non polymorphic
- [OpIE] impure, index aware, non polymorphic
Example
strLen := Op[string, int](func(s string) int {
	return len(s)
})

viewResult := MustGet(strLen, "hello world")
fmt.Println(viewResult)

//Ops are optics and can be composed.
lenLt4 := Compose(strLen, Lt(4))

data := []string{
	"lorem",
	"ipsum",
	"dolor",
	"sit",
	"amet",
}

filterResult := MustGet(SliceOf(Filtered(TraverseSlice[string](), lenLt4), len(data)), data)
fmt.Println(filterResult)

upper := Op(strings.ToUpper)
upperResult := MustModify(TraverseSlice[string](), upper, data)
fmt.Println(upperResult)
Output:

11
[sit]
[LOREM IPSUM DOLOR SIT AMET]

func OpE

func OpE[S, A any](op func(ctx context.Context, source S) (A, error)) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an Operator optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OperatorE] for a version that has an expression parameter.
- [Op] pure, non indexed,non polymorphic
- [OpI] pure, index aware,non polymorphic
- [OpE] impure, non indexed,non polymorphic
- [OpIE] impure, index aware, non polymorphic
Example
parseInt := OpE[string, int](func(ctx context.Context, s string) (int, error) {
	i, err := strconv.ParseInt(s, 10, 32)
	return int(i), err
})

viewResult, err := Get(parseInt, "11")
fmt.Println(viewResult, err)

lt4 := Compose(parseInt, Lt(4))

data := []string{
	"1",
	"2",
	"3",
	"4",
	"5",
}

filterResult, err := Get(SliceOf(Filtered(TraverseSlice[string](), lt4), len(data)), data)
fmt.Println(filterResult, err)

var overResult []int
overResult, err = Modify(TraverseSliceP[string, int](), parseInt, data)
fmt.Println(overResult, err)

badData := []string{
	"1",
	"2",
	"three",
	"4",
	"5",
}

_, err = Modify(TraverseSliceP[string, int](), parseInt, badData)
fmt.Println(err.Error())
Output:

11 <nil>
[1 2 3] <nil>
[1 2 3 4 5] <nil>
strconv.ParseInt: parsing "three": invalid syntax
optic error path:
	func1
	ValueI[int,string].value
	Traverse

func OpI

func OpI[I, S, A any](op func(I, S) A) Optic[Void, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OperatorI] for a version that has an expression parameter.
- [Op] pure, non indexed,non polymorphic
- [OpI] pure, index aware,non polymorphic
- [OpE] impure, non indexed,non polymorphic
- [OpIE] impure, index aware, non polymorphic
Example
indexFizzBuzz := OpI[int, string, string](func(index int, s string) string {

	index = index + 1

	if index%15 == 0 {
		return "fizz buzz"
	}

	if index%3 == 0 {
		return "fizz"
	}

	if index%5 == 0 {
		return "buzz"
	}

	return s
})

data := []string{
	"alpha",
	"beta",
	"gamma",
	"delta",
	"epsilon",
	"zeta",
}

var overResult []string = MustModifyI(TraverseSlice[string](), indexFizzBuzz, data)
fmt.Println(overResult)

//Index Ops can be composed.
eqFizz := ComposeLeft(indexFizzBuzz, Ne("fizz"))

filterResult := MustGet(SliceOf(FilteredI(TraverseSlice[string](), eqFizz), len(data)), data)
fmt.Println(filterResult)
Output:

[alpha beta fizz delta buzz fizz]
[alpha beta delta epsilon]

func OpIE

func OpIE[I, S, A any](opFnc func(context.Context, I, S) (A, error)) Optic[Void, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an Operator optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OperatorE] for a version that has an expression parameter.
- [Op] pure, non indexed,non polymorphic
- [OpI] pure, index aware,non polymorphic
- [OpE] impure, non indexed,non polymorphic
- [OpIE] impure, index aware, non polymorphic
Example
parseIntWithIndex := OpIE[int, string, int](func(ctx context.Context, index int, s string) (int, error) {
	i, err := strconv.ParseInt(s, 10, 32)
	return int(i) + (index * 100), err
})

data := []string{
	"1",
	"2",
	"3",
	"4",
	"5",
}

var overResult []int
overResult, err := ModifyI(TraverseSliceP[string, int](), parseIntWithIndex, data)
fmt.Println(overResult, err)

badData := []string{
	"1",
	"2",
	"three",
	"4",
	"5",
}

_, err = ModifyI(TraverseSliceP[string, int](), parseIntWithIndex, badData)
fmt.Println(err.Error())
Output:

[1 102 203 304 405] <nil>
strconv.ParseInt: parsing "three": invalid syntax
optic error path:
	func1
	Traverse

func OpIToOptic

func OpIToOptic[I, S, A any, RET TReturnOne, ERR any, ERRP any](o OperationI[I, S, A, RET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRP]) Optic[I, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]

func OpOnIx

func OpOnIx[A, I, R any, RET TReturnOne, ERR any](o Operation[I, R, RET, ERR]) Optic[Void, ValueI[I, A], ValueI[I, A], R, R, ReturnOne, ReadOnly, UniDir, ERR]

OpOnIx is a combinator that converts an Operator to an [IxOperator} that operates on the index instead of the focus.

See:

Example
data := []int{2, 4, 6, 8}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

//This operator will encode the slice index in the int in the 100s section
op := AddOp(
	OpToOpI[int]( //IxOp enables identity to be combined with other indexed operations
		Identity[int](),
	),
	ComposeLeft(
		OpOnIx[int]( //OpOnIx converts Identity to operate on the index instead of the focus
			Identity[int](),
		),
		Mul(100),
	),
)

var result []int = MustModifyI(
	optic,
	op,
	data,
)
fmt.Println(result)
Output:

[2 104 206 308]

func OpT2

func OpT2[S, T, A any](op func(a S, b T) A) Optic[Void, lo.Tuple2[S, T], lo.Tuple2[S, T], A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic that takes 2 parameters. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [Op] for a version that takes a single parameter
- [OpT2] pure, non indexed,non polymorphic
- [OpT2I] pure, index aware,non polymorphic
- [OpT2E] impure, non indexed,non polymorphic
- [OpT2IE] impure, index aware, non polymorphic

func OpT2Bind

func OpT2Bind[A, B, R any, RET TReturnOne, ERR any](op Operation[lo.Tuple2[A, B], R, RET, ERR], rightVal B) Optic[Void, A, A, R, R, ReturnOne, ReadOnly, UniDir, ERR]

func OpT2E

func OpT2E[S, T, A any](op func(ctx context.Context, a S, b T) (A, error)) Optic[Void, lo.Tuple2[S, T], lo.Tuple2[S, T], A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an Operator optic that takes 2 parameters. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OpE] for a version that takes a single parameters.
- [OpT2] pure, non indexed,non polymorphic
- [OpT2I] pure, index aware,non polymorphic
- [OpT2E] impure, non indexed,non polymorphic
- [OpT2IE] impure, index aware, non polymorphic

func OpT2I

func OpT2I[I, J, S, T, A any](op func(ia I, a S, ib J, b T) A) Optic[Void, lo.Tuple2[ValueI[I, S], ValueI[J, T]], lo.Tuple2[ValueI[I, S], ValueI[J, T]], A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic that takes 2 parameters. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OpI] for a version that takes a single parameters.
- [OpT2] pure, non indexed,non polymorphic
- [OpT2I] pure, index aware,non polymorphic
- [OpT2E] impure, non indexed,non polymorphic
- [OpT2IE] impure, index aware, non polymorphic

func OpT2IE

func OpT2IE[I, J, S, T, A any](opFnc func(ctx context.Context, i I, a S, j J, b T) (A, error)) Optic[Void, lo.Tuple2[ValueI[I, S], ValueI[J, T]], lo.Tuple2[ValueI[I, S], ValueI[J, T]], A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an Operator optic that takes 2 parameters. This constructor is a convenience wrapper for Operator without an expression parameter.

The following additional constructors are available.

. [OpIE] for a version that takes a single parameter.
- [OpT2] pure, non indexed,non polymorphic
- [OpT2I] pure, index aware,non polymorphic
- [OpT2E] impure, non indexed,non polymorphic
- [OpT2IE] impure, index aware, non polymorphic

func OpT2IToOptic

func OpT2IToOptic[I, S, A, R, LRW, RRW, ORW any, LRET, RRET, ORET TReturnOne, LDIR, RDIR, ODIR any, LERR, RERR, OERR any](left Optic[I, S, S, A, A, LRET, LRW, LDIR, LERR], op Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], R, R, ORET, ORW, ODIR, OERR], right Optic[I, S, S, A, A, RRET, RRW, RDIR, RERR]) Optic[Void, S, S, R, R, ORET, ReadOnly, UniDir, CompositionTree[CompositionTree[LERR, RERR], OERR]]

OpT2IToOptic returns an Operation that applies the given OperationI fnc on the values focused by the left and right optics.

Example
data := []int{2, 4, 6, 8}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

//This operator will encode the slice index of the int in the 100s section
op := OpT2IToOptic(
	OpToOpI[int]( //IxOp enables Identity to be used with indexed operators
		Identity[int](),
	),
	OpT2ToOpT2I[Void, int](AddT2[int]()), //IxOpT2 enables Add to be used with indexed operators
	ComposeLeft(
		ValueIIndex[int, int](),
		Mul(100),
	),
)

var result []int = MustModifyI(
	optic,
	op,
	data,
)
fmt.Println(result)
Output:

[2 104 206 308]

func OpT2IsoBind

func OpT2IsoBind[A any, RET TReturnOne, ERR any, RRET TReturnOne, RERR any](op Operation[lo.Tuple2[A, A], A, RET, ERR], revOp Operation[lo.Tuple2[A, A], A, RRET, RERR], rightVal A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, CompositionTree[ERR, RERR]]

func OpT2ToOpT2I

func OpT2ToOpT2I[J, S, A any, RET TReturnOne, ERR any](op Operation[lo.Tuple2[S, S], A, RET, ERR]) Optic[Void, lo.Tuple2[ValueI[J, S], ValueI[J, S]], lo.Tuple2[ValueI[J, S], ValueI[J, S]], A, A, ReturnOne, ReadOnly, UniDir, ERR]
Example
data := []int{2, 4, 6, 8}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

//This operator will encode the slice index of the int in the 100s section
op := OpT2IToOptic(
	OpToOpI[int]( //OpToOpI enables Identity to be used with indexed operators
		Identity[int](),
	),
	OpT2ToOpT2I[Void, int](AddT2[int]()), //OpT2ToOpT2I enables Add to be used with indexed operators
	ComposeLeft(
		ValueIIndex[int, int](),
		Mul(100),
	),
)

var result []int = MustModifyI(
	optic,
	op,
	data,
)
fmt.Println(result)
Output:

[2 104 206 308]

func OpT2ToOptic

func OpT2ToOptic[I, S, A, R, ORW any, LRET, RRET TReturnOne, ORET any, ODIR any, LERR, RERR, OERR any](left Operation[S, A, LRET, LERR], op Optic[I, lo.Tuple2[A, A], lo.Tuple2[A, A], R, R, ORET, ORW, ODIR, OERR], right Operation[S, A, RRET, RERR]) Optic[I, S, S, R, R, ORET, ReadOnly, UniDir, CompositionTree[CompositionTree[LERR, RERR], OERR]]
Example
data := [][]int{
	{1, 1},
	{1, 2},
	{2, 1},
	{2, 2},
}

//returns a operator that returns s[0] * s[1] of a slice
operator := OpT2ToOptic(
	FirstOrDefault(Index(TraverseSlice[int](), 0), 0),
	MulT2[int](),
	FirstOrDefault(Index(TraverseSlice[int](), 1), 0),
)

var overResult []int = MustModify(
	TraverseSliceP[[]int, int](),
	operator,
	data,
)
fmt.Println(overResult)
Output:

[1 2 2 4]

func OpToOpI

func OpToOpI[I, S, A any, RET TReturnOne, ERR any](fnc Operation[S, A, RET, ERR]) Optic[Void, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, ERR]

OpToOpI is a combinator that converts an Operator to an OperatorI that ignores the index when performing the operation.

See:

  • OpOnIx for a combinator that converts an Operator to operate on the index instead of the focus
Example
data := []int{2, 4, 6, 8}

//This optic focuses each int in the slice
optic := TraverseSlice[int]()

//This operator will encode the slice index in the int in the 100s section
op := AddOp(
	OpToOpI[int]( //IxOp enables non indexed operations to be combined with indexed operations.
		Identity[int](),
	),
	ComposeLeft(
		ValueIIndex[int, int](),
		Mul(100),
	),
)

var result []int = MustModifyI(
	optic,
	op,
	data,
)
fmt.Println(result)
Output:

[2 104 206 308]

func OpToOptic

func OpToOptic[S, A any, RET TReturnOne, ERR any](o Operation[S, A, RET, ERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, ERR]

func Operator

func Operator[S, A any](
	opFnc func(source S) A,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic.

The following additional constructors are available.

. [Op] for a version that does not require an [expr.OpticExpression],
- [Operator] pure, non indexed,non polymorphic
- [OperatorI] pure, index aware,non polymorphic
- [OperatorE] impure, non indexed,non polymorphic
- [OperatorIE] impure, index aware, non polymorphic
Example
strLen := Operator[string, int](
	func(s string) int {
		return len(s)
	},
	ExprCustom("ExampleOperator"),
)

viewResult := MustGet(strLen, "hello world")
fmt.Println(viewResult)

//Ops are optics and can be composed.
lenLt4 := Compose(strLen, Lt(4))

data := []string{
	"lorem",
	"ipsum",
	"dolor",
	"sit",
	"amet",
}

filterResult := MustGet(SliceOf(Filtered(TraverseSlice[string](), lenLt4), len(data)), data)
fmt.Println(filterResult)

upper := Op(strings.ToUpper)
upperResult := MustModify(TraverseSlice[string](), upper, data)
fmt.Println(upperResult)
Output:

11
[sit]
[LOREM IPSUM DOLOR SIT AMET]

func OperatorE

func OperatorE[S, A any](
	opFnc func(ctx context.Context, source S) (A, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an Operator optic.

The following additional constructors are available.

. [OpE] for a version that does not require an [expr.OpticExpression],
- [Operator] pure, non indexed,non polymorphic
- [OperatorI] pure, index aware,non polymorphic
- [OperatorE] impure, non indexed,non polymorphic
- [OperatorIE] impure, index aware, non polymorphic
Example
parseInt := OperatorE[string, int](
	func(ctx context.Context, s string) (int, error) {
		i, err := strconv.ParseInt(s, 10, 32)
		return int(i), err
	},
	ExprCustom("ExampleOperatorR"),
)

viewResult, err := Get(parseInt, "11")
fmt.Println(viewResult, err)

lt4 := Compose(parseInt, Lt(4))

data := []string{
	"1",
	"2",
	"3",
	"4",
	"5",
}

filterResult, err := Get(SliceOf(Filtered(TraverseSlice[string](), lt4), len(data)), data)
fmt.Println(filterResult, err)

var overResult []int
overResult, err = Modify(TraverseSliceP[string, int](), parseInt, data)
fmt.Println(overResult, err)

badData := []string{
	"1",
	"2",
	"three",
	"4",
	"5",
}

_, err = Modify(TraverseSliceP[string, int](), parseInt, badData)
fmt.Println(err.Error())
Output:

11 <nil>
[1 2 3] <nil>
[1 2 3 4 5] <nil>
strconv.ParseInt: parsing "three": invalid syntax
optic error path:
	Custom(ExampleOperatorR)
	ValueI[int,string].value
	Traverse

func OperatorI

func OperatorI[I, S, A any](
	opFnc func(I, S) A,
	exprDef ExpressionDef,
) Optic[Void, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an Operator optic.

The following additional constructors are available.

. [OpI] for a version that does not require an [expr.OpticExpression],
- [Operator] pure, non indexed,non polymorphic
- [OperatorI] pure, index aware,non polymorphic
- [OperatorE] impure, non indexed,non polymorphic
- [OperatorIE] impure, index aware, non polymorphic
Example
indexFizzBuzz := OperatorI[int, string, string](
	func(index int, s string) string {

		index = index + 1

		if index%15 == 0 {
			return "fizz buzz"
		}

		if index%3 == 0 {
			return "fizz"
		}

		if index%5 == 0 {
			return "buzz"
		}

		return s
	},
	ExprCustom("ExampleOperatorI"),
)

data := []string{
	"alpha",
	"beta",
	"gamma",
	"delta",
	"epsilon",
	"zeta",
}

var overResult []string = MustModifyI(TraverseSlice[string](), indexFizzBuzz, data)
fmt.Println(overResult)

//Index Ops can be composed.
eqFizz := ComposeLeft(indexFizzBuzz, Ne("fizz"))

filterResult := MustGet(SliceOf(FilteredI(TraverseSlice[string](), eqFizz), len(data)), data)
fmt.Println(filterResult)
Output:

[alpha beta fizz delta buzz fizz]
[alpha beta delta epsilon]

func OperatorIE

func OperatorIE[I, S, A, ERR any](
	opFnc func(ctx context.Context, index I, source S) (A, error),
	exprDef ExpressionDef,
) Optic[Void, ValueI[I, S], ValueI[I, S], A, A, ReturnOne, ReadOnly, UniDir, ERR]

Constructor for an Operator optic.

The following additional constructors are available.

. [OpIE] for a version that does not require an [expr.OpticExpression],
- [Operator] pure, non indexed,non polymorphic
- [OperatorI] pure, index aware,non polymorphic
- [OperatorE] impure, non indexed,non polymorphic
- [OperatorIE] impure, index aware, non polymorphic
Example
parseIntWithIndex := OperatorIE[int, string, int, Err](
	func(ctx context.Context, index int, s string) (int, error) {
		i, err := strconv.ParseInt(s, 10, 32)
		return int(i) + (index * 100), err
	},
	ExprCustom("ExampleOperatorF"))

data := []string{
	"1",
	"2",
	"3",
	"4",
	"5",
}

var overResult []int
overResult, err := ModifyI(TraverseSliceP[string, int](), parseIntWithIndex, data)
fmt.Println(overResult, err)

badData := []string{
	"1",
	"2",
	"three",
	"4",
	"5",
}

_, err = ModifyI(TraverseSliceP[string, int](), parseIntWithIndex, badData)
fmt.Println(err.Error())
Output:

[1 102 203 304 405] <nil>
strconv.ParseInt: parsing "three": invalid syntax
optic error path:
	Custom(ExampleOperatorF)
	Traverse

func OptionOfFirst

func OptionOfFirst[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, mo.Option[A], mo.Option[B], ReturnOne, ReadOnly, UniDir, ERR]

OptionOfFirst focuses the first element wrapped in a mo.Option or mo.None if no elements are focused.

func Or

Or returns an Operation that performs a logical or with a constant value.

See:

  • [IOr] for an OperationI version
  • OrOp for a version that is applied to the focus of 2 getters.

func OrOp

func OrOp[S, LERR, RERR any](left Predicate[S, LERR], right Predicate[S, RERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

OrOp returns an Operation that logically ors the value of the left getter with the right getters value

See:

  • Or for the constant version
Example
data := []lo.Tuple2[int, int]{
	lo.T2(1, 1),
	lo.T2(1, 2),
	lo.T2(2, 1),
	lo.T2(2, 2),
	lo.T2(3, 1),
}

//returns a predicate that matches if A>B in the tuple
predicateGt := GtOp(T2A[int, int](), T2B[int, int]())
//returns a predicate that matches if A==2 in the tuple
predicateEq2 := Compose(T2A[int, int](), Eq(2))

//These 2 predicates are compatible as they have an int source type. They can be combined into an or predicate
predicateAnd := OrOp(predicateGt, predicateEq2)

//Returns an optic that filters a slice of int tuples using the predicate
filterOptic := Filtered(TraverseSlice[lo.Tuple2[int, int]](), predicateAnd)
filtered := MustGet(SliceOf(filterOptic, len(data)), data)
fmt.Println(filtered)

//We can focus on this composite filter predicate and modify the focused element by adding 10
var overResult []lo.Tuple2[int, int] = MustModify(Compose(filterOptic, T2B[int, int]()), Add(10), data)
fmt.Println(overResult)
Output:

[{2 1} {2 2} {3 1}]
[{1 1} {1 2} {2 11} {2 12} {3 11}]

func OrT2

OrT2 returns an BinaryOp that performs a logical or

See:

  • Or for a unary version.
  • OrOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []bool{true, false, true, true, true}

//The Or function can be converted to a Reducer to detect if any focused values are true in a traversal where the empty traversal is considered to be all true values.
result, ok := MustGetFirst(Reduce(TraverseSlice[bool](), AsReducer(true, OrT2())), data)
fmt.Println(result, ok)
Output:

true true

func OrderBy

func OrderBy[A any, C cmp.Ordered, RET TReturnOne, ERR any](cmpBy Operation[A, C, RET, ERR]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

Constructor for an OrderByPredicate optic.

The following additional constructors are available.

The cmpBy Operation should focus on a cmp.Ordered value that will be used to order by.

See:

  • OrderByOp for a constructor that takes an arbitrary function to perform ordering.
  • OrderByN for a combinator enables ordering on multiple criteria
Example
type Person struct {
	name string
	age  int
}

personAge := FieldLens(func(source *Person) *int { return &source.age })

data := []Person{
	{
		name: "Alice",
		age:  46,
	},
	{
		name: "Bob",
		age:  45,
	},
	{
		name: "Carol",
		age:  44,
	},
}

optic := Ordered(
	TraverseSlice[Person](),
	OrderBy(
		personAge,
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[{Carol 44} {Bob 45} {Alice 46}]

func OrderBy2

func OrderBy2[A, ERR1, ERR2 any](orderBy1 OrderByPredicate[A, ERR1], orderBy2 OrderByPredicate[A, ERR2]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR1, ERR2]]

The OrderBy2 combinator combines 2 OrderByPredicate into a single OrderByPredicate applying each order by in sequence.

See:

  • OrderBy2, OrderBy3, OrderBy4 for other versions that allows the ERR to differ between orderBys
  • OrderByN for a versions that accepts an arbitrary number of orderbys but requires they all have the same ERR
Example
type Person struct {
	name string
	age  int
}

personName := FieldLens(func(source *Person) *string { return &source.name })
personAge := FieldLens(func(source *Person) *int { return &source.age })

data := []Person{
	{
		name: "Bob",
		age:  46,
	},
	{
		name: "Alice",
		age:  46,
	},
	{
		name: "Carol",
		age:  44,
	},
}

optic := Ordered(
	TraverseSlice[Person](),
	OrderBy2(
		OrderBy(personAge),
		OrderBy(personName),
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[{Carol 44} {Alice 46} {Bob 46}]

func OrderBy3

func OrderBy3[A, ERR1, ERR2, ERR3 any](orderBy1 OrderByPredicate[A, ERR1], orderBy2 OrderByPredicate[A, ERR2], orderBy3 OrderByPredicate[A, ERR3]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[CompositionTree[ERR1, ERR2], ERR3]]

The OrderBy3 combinator combines 3 OrderByPredicate into a single OrderByPredicate applying each order by in sequence.

See:

  • OrderBy2, OrderBy3, OrderBy4 for other versions that allows the ERR to differ between orderBys
  • OrderByN for a versions that accepts an arbitrary number of orderbys but requires they all have the same ERR

func OrderBy4

func OrderBy4[A, ERR1, ERR2, ERR3, ERR4 any](orderBy1 OrderByPredicate[A, ERR1], orderBy2 OrderByPredicate[A, ERR2], orderBy3 OrderByPredicate[A, ERR3], orderBy4 OrderByPredicate[A, ERR4]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4]]]

The OrderBy4 combinator combines 4 OrderByPredicate into a single OrderByPredicate applying each order by in sequence.

See:

  • OrderBy2, OrderBy3, OrderBy4 for other versions that allows the ERR to differ between orderBys
  • OrderByN for a versions that accepts an arbitrary number of orderbys but requires they all have the same ERR

func OrderByI

func OrderByI[I, A any, C cmp.Ordered, RET TReturnOne, ERR any](cmpBy OperationI[I, A, C, RET, ERR]) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

Constructor for an OrderByPredicateI optic.

The following additional constructors are available.

The cmpBy OperationI should focus on a cmp.Ordered] value that will be used to order by.

See:

  • OrderByOpI for a constructor that takes an arbitrary function to perform ordering.
  • [OrderByNI] for a combinator enables ordering on multiple criteria
Example
data := map[int]string{
	4: "alpha",
	3: "beta",
	2: "gamma",
	1: "delta",
}

optic := OrderedI(
	TraverseMap[int, string](),
	OrderByI(
		ValueIIndex[int, string](),
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[delta gamma beta alpha]

func OrderByN

func OrderByN[A, ERR any](orderBys ...OrderByPredicate[A, ERR]) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

The OrderByN combinator combines multiple OrderByPredicate into a single OrderByPredicate applying each order by in sequence.

See:

Example
type Person struct {
	name string
	age  int
}

personName := FieldLens(func(source *Person) *string { return &source.name })
personAge := FieldLens(func(source *Person) *int { return &source.age })

data := []Person{
	{
		name: "Bob",
		age:  46,
	},
	{
		name: "Alice",
		age:  46,
	},
	{
		name: "Carol",
		age:  44,
	},
}

optic := Ordered(
	TraverseSlice[Person](),
	OrderByN(
		OrderBy(personAge),
		OrderBy(personName),
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[{Carol 44} {Alice 46} {Bob 46}]

func OrderByOpE

func OrderByOpE[A any](less func(ctx context.Context, valueLeft A, valueRight A) (bool, error)) Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], bool, bool, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an OrderByPredicate optic. This constructor is a convenience wrapper for OperatorE without an expression parameter.

The less function should return true if valueLeft is less than valueRight.

The following additional constructors are available.

See:

Example
data := []string{"1", "10", "2", "9", "3", "8", "4", "7", "5", "6"}

optic := Ordered(
	TraverseSlice[string](),
	OrderByOpE(
		func(ctx context.Context, left, right string) (bool, error) {

			leftInt, err := strconv.ParseInt(left, 10, 32)
			if err != nil {
				return false, err
			}

			rightInt, err := strconv.ParseInt(right, 10, 32)
			if err != nil {
				return false, err
			}

			return leftInt < rightInt, nil
		},
	),
)

result, err := Get(SliceOf(optic, len(data)), data)
fmt.Println(result, err)
Output:

[1 2 3 4 5 6 7 8 9 10] <nil>

func OrderByOpI

func OrderByOpI[I, A any](less func(indexLeft I, valueLeft A, indexRight I, valueRight A) bool) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Constructor for an OrderByPredicate optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The less function should return true if valueLeft is less than valueRight.

The following additional constructors are available.

See:

Example
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

optic := OrderedI(
	TraverseSlice[int](),
	OrderByOpI(
		func(indexLeft int, left int, indexRight int, right int) bool {
			return -indexLeft < -indexRight
		},
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[10 9 8 7 6 5 4 3 2 1]

func OrderByOpIE

func OrderByOpIE[I, A any](less func(ctx context.Context, indexLeft I, valueLeft A, indexRight I, valueRight A) (bool, error)) Optic[Void, lo.Tuple2[ValueI[I, A], ValueI[I, A]], lo.Tuple2[ValueI[I, A], ValueI[I, A]], bool, bool, ReturnOne, ReadOnly, UniDir, Err]

Constructor for an OrderByPredicate optic. This constructor is a convenience wrapper for OperatorE without an expression parameter.

The less function should return true if valueLeft is less than valueRight.

The following additional constructors are available.

See:

Example
data := []string{"1", "10", "2", "9", "3", "8", "4", "7", "5", "6"}

optic := OrderedI(
	TraverseSlice[string](),
	OrderByOpIE(
		func(ctx context.Context, indexLeft int, left string, indexRight int, right string) (bool, error) {

			leftInt, err := strconv.ParseInt(left, 10, 32)
			if err != nil {
				return false, err
			}

			rightInt, err := strconv.ParseInt(right, 10, 32)
			if err != nil {
				return false, err
			}

			return leftInt*int64(indexLeft) < rightInt*int64(indexRight), nil
		},
	),
)

result, err := Get(SliceOf(optic, len(data)), data)
fmt.Println(result, err)
Output:

[1 2 10 3 4 9 5 8 7 6] <nil>

func Ordered

func Ordered[I, S, T, A, B any, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], orderBy OrderByPredicate[A, PERR]) Optic[I, S, T, A, B, RET, RW, UniDir, CompositionTree[ERR, PERR]]

The Ordered combinator focuses on the elements of the given optic in the order defined by the orderBy predicate

Note: under modification the elements are focused in order but the result retains the original order.

See:

  • OrderedCol for a operation that re-orders a collection.
  • OrderedI for an index aware version.
Example
data := []int{9, 8, 3, 7, 2, 5, 1, 4, 10, 6}

optic := Taking(
	Ordered(
		TraverseSlice[int](),
		OrderBy(Identity[int]()),
	),
	5,
)

var getResult []int = MustGet(SliceOf(optic, 5), data)
fmt.Println(getResult)

var modifyResult []int = MustModify(optic, Mul(100), data)
fmt.Println(modifyResult)
Output:

[1 2 3 4 5]
[9 8 300 7 200 500 100 400 10 6]

func OrderedCol

func OrderedCol[I comparable, A any, ERR any](orderBy OrderByPredicate[A, ERR]) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadWrite, UniDir, ERR]

OrderedCol returns a collection operation that sorts an Collection according to the given OrderByPredicate

See:

  • [SortP] for a polymorphic version
  • OrderedColI for an index aware version
  • Ordered for a non collection operation version.

func OrderedColI

func OrderedColI[I, A any, ERR any](orderBy OrderByPredicateI[I, A, ERR], ixMatch func(a, b I) bool) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadWrite, UniDir, ERR]

OrderedColI returns an index aware collection operation that sorts an Collection according to the given OrderByPredicateI

See:

  • OrderedCol for a non index aware version
  • OrderedI for a non collection operation version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

var result []string = MustModify(
	SliceToCol[string](),
	OrderedColI[int, string](
		OrderByI(
			OpOnIx[string](
				Negate[int](),
			),
		),
		IxMatchComparable[int](),
	),
	data,
)

fmt.Println(result)
Output:

[delta gamma beta alpha]

func OrderedI

func OrderedI[I, S, T, A, B any, RET, RW, DIR, ERR, PERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], orderBy OrderByPredicateI[I, A, PERR]) Optic[I, S, T, A, B, RET, RW, UniDir, CompositionTree[ERR, PERR]]

The OrderedI combinator focuses on the elements of the given optic in the order defined by the orderBy predicate

Note: under modification the elements are focused in order but the result retains the original order.

See:

  • OrderedColI for a operation that re-orders a collection.
  • Ordered for a non index aware version.
Example
data := map[string]int{
	"z": 1,
	"y": 2,
	"x": 3,
	"w": 4,
}

optic := Taking(
	OrderedI(
		TraverseMap[string, int](),
		OrderBy(ValueIIndex[string, int]()),
	),
	2,
)

var getResult map[string]int
getResult, err := Get(MapOf(optic, 5), data)
fmt.Println(getResult, err)

var modifyResult map[string]int = MustModify(optic, Mul(100), data)
fmt.Println(modifyResult)
Output:

map[w:4 x:3] <nil>
map[w:400 x:300 y:2 z:1]

func OrderedSlice

func OrderedSlice[A any, ERR any](orderBy OrderByPredicate[A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, UniDir, ERR]

OrderedSlice applies the Ordered operation to a Slice

See: - OrderedSliceI for an index aware version

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		OrderedSlice(OrderBy(Identity[string]())),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	OrderedSlice(OrderBy(Identity[string]())),
	data,
)
fmt.Println(modifyRes)
Output:

[alpha beta delta gamma]
{1 [alpha beta delta gamma]}

func OrderedSliceI

func OrderedSliceI[A any, ERR any](orderBy OrderByPredicateI[int, A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, UniDir, ERR]

OrderedSliceI applies the OrderedI operation to a Slice

See: - OrderedSlice for a non index aware version

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		OrderedSliceI(
			Desc(
				OrderByI(
					ValueIIndex[int, string](),
				),
			),
		),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	OrderedSliceI(Desc(OrderByI(ValueIIndex[int, string]()))),
	data,
)
fmt.Println(modifyRes)
Output:

[delta gamma beta alpha]
{1 [delta gamma beta alpha]}

func OrderedString

func OrderedString[ERR any](orderBy OrderByPredicate[rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadWrite, UniDir, ERR]

OrderedString applies the Ordered operation to a String

See: - OrderedStringI for an index aware version

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		OrderedString(OrderBy(Identity[rune]())),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	OrderedString(OrderBy(Identity[rune]())),
	data,
)
fmt.Println(modifyRes)
Output:

Ladeeiilmmmoooprrssttu
{1     Ladeeiilmmmoooprrssttu}

func OrderedStringI

func OrderedStringI[ERR any](orderBy OrderByPredicateI[int, rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadWrite, UniDir, ERR]

OrderedStringI applies the OrderedI operation to a String

See: - OrderedString for a non index aware version

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		OrderedStringI(
			Desc(
				OrderByI(
					ValueIIndex[int, rune](),
				),
			),
		),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	OrderedStringI(Desc(OrderByI(ValueIIndex[int, rune]()))),
	data,
)
fmt.Println(modifyRes)
Output:

tema tis rolod muspi meroL
{1 tema tis rolod muspi meroL}

func ParseFloat

func ParseFloat[T Real](fmt byte, prec int, bitSize int) Optic[Void, string, string, T, T, ReturnOne, ReadWrite, BiDir, Err]

ParseFloat returns a Iso that parses the value to an float.

The fmt and prec parameters corresponds to the strconv.FormatFloat parameters with the same name. The bitSize parameter corresponds to the strconv.ParseFloat parameter with the same name.

See:

Example
data := []string{"1.1", "2.2", "3.3"}

var composedResult []string
composedResult, err := Modify(
	Compose(
		TraverseSlice[string](),
		ParseFloat[float64]('f', -1, 64),
	),
	Mul(2.0),
	data,
)
fmt.Println(composedResult, err)
Output:

[2.2 4.4 6.6] <nil>

func ParseFloatP

func ParseFloatP[T Real](bitSize int) Optic[Void, string, T, T, T, ReturnOne, ReadWrite, BiDir, Err]

ParseFloatP returns a polymorphic Iso that parses the value to an float.

The base and bitSize parameters correspond to the strconv.ParseFloat parameters with the same name.

Example
data := []string{"1.1", "2.2", "3.3"}

var composedResult []float64
composedResult, err := Modify(
	Compose(
		TraverseSliceP[string, float64](),
		ParseFloatP[float64](64),
	),
	Mul(2.0),
	data,
)
fmt.Println(composedResult, err)
Output:

[2.2 4.4 6.6] <nil>

func ParseInt

func ParseInt[T Real](base int, bitSize int) Optic[Void, string, string, T, T, ReturnOne, ReadWrite, BiDir, Err]

ParseInt returns an Iso that parses the value to an int. An error is returned if the string cannot be parsed

The base and bitSize parameters correspond to the strconv.ParseInt parameters with the same name. See:

Example
data := []string{"1", "2", "3"}

var composedResult []string
composedResult, err := Modify(
	Compose(
		TraverseSlice[string](),
		ParseInt[int](10, 32),
	),
	Mul(2),
	data,
)
fmt.Println(composedResult, err)
Output:

[2 4 6] <nil>

func ParseIntP

func ParseIntP[T Real](base int, bitSize int) Optic[Void, string, T, T, T, ReturnOne, ReadWrite, BiDir, Err]

ParseIntP returns a polymorphic Iso that parses the value to an int. An error is returned if the string cannot be parsed

The base and bitSize parameters correspond to the strconv.ParseInt parameters with the same name. See:

  • ParseInt for a non polymorphic version.
Example
data := []string{"1", "2", "3"}

var composedResult []int
composedResult, err := Modify(
	Compose(
		TraverseSliceP[string, int](),
		ParseIntP[int](10, 32),
	),
	Mul(2),
	data,
)
fmt.Println(composedResult, err)
Output:

[2 4 6] <nil>

func Polymorphic

func Polymorphic[TP, BP, I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, TP, A, BP, RET, ReadOnly, UniDir, ERR]

The Polymorphic combinator enables any optic to be made polymorphic at the cost of becoming ReadOnly

Example
data := []ValueI[int, string]{
	ValI(0, "1"),
	ValI(1, "2"),
	ValI(3, "3"),
}

optic := Compose3(
	TraverseSliceP[ValueI[int, string], ValueI[int, int]](),
	Polymorphic[ValueI[int, int], int](ValueIValue[int, string]()),
	ParseIntP[int](10, 0),
)

res, err := Get(SliceOf(optic, 3), data)
fmt.Println(res, err)
Output:

[1 2 3] <nil>

func Pow

Pow returns a Iso that raises a value to a constant power.

See:

  • PowOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, float64]{
	lo.T2("a", 1.0),
	lo.T2("b", 2.0),
	lo.T2("c", 3.0),
	lo.T2("d", 4.0),
	lo.T2("e", 5.0),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, float64]](), T2B[string, float64]())

//Raise each focused value to the power of 2.
var overResult []lo.Tuple2[string, float64] = MustModify(optic, Pow(2.0), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition raises to the power 2 then adds 1
var composedResult []lo.Tuple2[string, float64] = MustModify(optic, Compose(Pow(2.0), Add(1.0)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a raise to the power 2 context
//But when the result is built the value is lowered by root 2 again to return it to the original context
var preComposedResult []lo.Tuple2[string, float64] = MustModify(Compose(optic, Pow(2.0)), Add(1.0), data)
fmt.Println(preComposedResult)
Output:

[{a 1} {b 4} {c 9} {d 16} {e 25}]
[{a 2} {b 5} {c 10} {d 17} {e 26}]
[{a 1.4142135623730951} {b 2.23606797749979} {c 3.1622776601683795} {d 4.123105625617661} {e 5.0990195135927845}]

func PowOp

func PowOp[S any, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, float64, LRET, LERR], right Operation[S, float64, RRET, RERR]) Optic[Void, S, S, float64, float64, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

PowOp returns an Operation expression that raises the left focus to the power of the right focus.

See:

  • Pow for the constant version.
Example
data := []lo.Tuple2[float64, float64]{
	lo.T2(1.0, 5.0),
	lo.T2(2.0, 4.0),
	lo.T2(3.0, 3.0),
	lo.T2(4.0, 2.0),
	lo.T2(5.0, 1.0),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[float64, float64]()
rightOptic := T2B[float64, float64]()

//Create a getter that applies the Pow function to the focuses of both optics
power := PowOp(leftOptic, rightOptic)

var singleValueResult float64 = MustGet(power, lo.T2(2.0, 4.0))
fmt.Println(singleValueResult) // 16

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []float64 = MustModify(TraverseSliceP[lo.Tuple2[float64, float64], float64](), power, data)
fmt.Println(overResult) // [1 16 27 16 5]
Output:

16
[1 16 27 16 5]

func PowT2

PowT2 returns an BinaryOp that raises A to the power B.

See:

  • Pow for a unary version.
  • PowOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[float64, float64]{
	lo.T2(5.0, 2.0),
	lo.T2(6.0, 2.0),
	lo.T2(5.0, 3.0),
	lo.T2(6.0, 3.0),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[float64, float64]](),
	PowT2(),
)

var res []float64 = MustGet(
	SliceOf(
		optic,
		4,
	),
	data,
)
fmt.Println(res)
Output:

[25 36 125 216]

func PredEToOptic

func PredEToOptic[S any](pred PredicateE[S]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, Err]

func PredOnIx

func PredOnIx[A, I, ERR any](o Predicate[I, ERR]) Optic[Void, ValueI[I, A], ValueI[I, A], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

PredOnIx is a combinator that converts an Operator to an [IxOperator} that operates on the index instead of the focus.

Example
data := []int{
	10,
	20,
	30,
	40,
}

//PredIx converts Even to operate on the index rather than the focused value
evenIndex := PredOnIx[int](Even[int]())

result, err := Modify(FilteredI(TraverseSlice[int](), evenIndex), Mul(10), data)
fmt.Println(result, err)
Output:

[100 20 300 40] <nil>

func PredT2ToOpT2I

func PredT2ToOpT2I[I, J, S, T, ERR any](fnc Predicate[lo.Tuple2[S, T], ERR]) Optic[Void, lo.Tuple2[ValueI[I, S], ValueI[J, T]], lo.Tuple2[ValueI[I, S], ValueI[J, T]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

PredT2ToOpT2I is a combinator that converts a 2 parameter Predicate to a 2 parameter PredicateI that ignores the index when performing the operation.

See:

func PredT2ToOptic

func PredT2ToOptic[I, S, R, ORW any, ORET, ODIR any, OERR, LERR, RERR any](left Predicate[S, LERR], op Optic[I, lo.Tuple2[bool, bool], lo.Tuple2[bool, bool], R, R, ORET, ORW, ODIR, OERR], right Predicate[S, RERR]) Optic[I, S, S, R, R, ORET, ReadOnly, UniDir, CompositionTree[CompositionTree[LERR, RERR], OERR]]
Example
data := []lo.Tuple2[bool, bool]{
	lo.T2(false, false),
	lo.T2(false, true),
	lo.T2(true, false),
	lo.T2(true, true),
}

//returns a predicate that matches if A && B in the tuple
predicate := PredT2ToOptic(T2A[bool, bool](), AndT2(), T2B[bool, bool]())

filtered := MustGet(
	SliceOf(
		Filtered(
			TraverseSlice[lo.Tuple2[bool, bool]](), predicate,
		),
		len(data),
	),
	data,
)
fmt.Println(filtered)

var overResult []bool = MustModify(
	TraverseSliceP[lo.Tuple2[bool, bool], bool](),
	predicate,
	data,
)
fmt.Println(overResult)
Output:

[{true true}]
[false false false true]

func PredToOpI

func PredToOpI[I, S, ERR any](fnc Predicate[S, ERR]) Optic[Void, ValueI[I, S], ValueI[I, S], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

PredToOpI is a combinator that converts a Predicate to an OperatorI that ignores the index when performing the operation.

See:

  • OpOnIx for a combinator that converts an Operator to operate on the index instead of the focus
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each int in the slice
optic := TraverseSlice[string]()

igt := GtI[string](0)
lt := Ne("gamma")

//Indexed and non indexed predicates can be mixed by wrapping the non indexed operator
andOp := AndOp(igt, PredToOpI[int](lt))

filter := FilteredI(optic, andOp)

var result []string = MustGet(SliceOf(filter, len(data)), data)
fmt.Println(result)
Output:

[beta delta]

func PredToOptic

func PredToOptic[S, ERR any](pred Predicate[S, ERR]) Optic[Void, S, S, bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func Prefixed

func Prefixed[I, J, S, A any, RET TReturnOne, RW TReadWrite, DIR, ERR any, PERR any](path Optic[I, S, S, Collection[J, A, ERR], Collection[J, A, ERR], RET, RW, DIR, ERR], valMatch Predicate[lo.Tuple2[A, A], PERR], ix J, val A) Optic[Void, S, S, S, S, ReturnMany, ReadWrite, BiDir, CompositionTree[ERR, PERR]]

func Prepend

func Prepend[A any](toAppend ...A) Optic[Void, Collection[int, A, Pure], Collection[int, A, Pure], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadOnly, UniDir, Pure]

Prepend returns a Lens that appends additional integer indexed elements to the start of the source Collection.

See:

  • [PrependP] for a polymorphic version
  • PrependCol for a version that takes an arbitrary Collection as a parameter
  • AppendCol for an append version
Example
data := []string{
	"gamma",
	"delta",
}

var result []string = MustModify(
	SliceToCol[string](),
	Prepend("alpha", "beta"),
	data,
)

fmt.Println(result)
Output:

[alpha beta gamma delta]

func PrependCol

func PrependCol[I, A, ERR any](toPrepend Collection[I, A, ERR]) Optic[Void, Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadOnly, UniDir, ERR]

PrependCol returns a Lens that prepends additional elements to the start of the source Collection.

See:

  • [PrependColP] for a polymorphic version
  • AppendCol for an append version
  • [Prepending] for a non collection version
Example
data := []string{
	"gamma",
	"delta",
}

var result []string = MustModify(
	SliceToCol[string](),
	PrependCol(
		ValCol("alpha", "beta"),
	),
	data,
)

fmt.Println(result)
Output:

[alpha beta gamma delta]

func PrependColT2

func PrependColT2[I, A, ERR any]() Optic[Void, lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], lo.Tuple2[Collection[I, A, ERR], Collection[I, A, ERR]], Collection[I, A, ERR], Collection[I, A, ERR], ReturnOne, ReadOnly, UniDir, ERR]

func PrependColTypeT2

func PrependColTypeT2[I, S, A any, ERR any](s CollectionType[I, S, S, A, A, ERR]) Optic[Void, lo.Tuple2[S, S], lo.Tuple2[S, S], S, S, ReturnOne, ReadOnly, UniDir, ERR]

func PrependMapT2

func PrependMapT2[K comparable, S any, I, ERR any]() Optic[Void, lo.Tuple2[map[K]S, map[K]S], lo.Tuple2[map[K]S, map[K]S], map[K]S, map[K]S, ReturnOne, ReadOnly, UniDir, ERR]

PrependMapT2 applies the PrependColT2 operation to a Map

func PrependSlice

func PrependSlice[A any, ERR any](toPrepend Collection[int, A, ERR]) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadOnly, UniDir, ERR]

PrependSlice applies the Prepend operation to a Slice

Example
data := lo.T2(
	1,
	[]string{
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		PrependSlice(ValCol("alpha", "beta")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	PrependSlice(ValCol("alpha", "beta")),
	data,
)
fmt.Println(modifyRes)
Output:

[alpha beta gamma delta]
{1 [alpha beta gamma delta]}

func PrependSliceT2

func PrependSliceT2[A any, I, ERR any]() Optic[Void, lo.Tuple2[[]A, []A], lo.Tuple2[[]A, []A], []A, []A, ReturnOne, ReadOnly, UniDir, ERR]

PrependSliceT2 applies the PrependColT2 operation to a Slice

func PrependString

func PrependString[ERR any](toPrepend Collection[int, rune, ERR]) Optic[Void, string, string, string, string, ReturnOne, ReadOnly, UniDir, ERR]

PrependString applies the Prepend operation to a String

Example
data := lo.T2(1, "ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		PrependString(StringCol("Lorem ")),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	PrependString(StringCol("Lorem ")),
	data,
)
fmt.Println(modifyRes)
Output:

Lorem ipsum dolor sit amet
{1 Lorem ipsum dolor sit amet}

func PrependStringT2

func PrependStringT2[I, ERR any]() Optic[Void, lo.Tuple2[string, string], lo.Tuple2[string, string], string, string, ReturnOne, ReadOnly, UniDir, ERR]

PrependStringT2 applies the PrependColT2 operation to a String

func Present

func Present[A any]() Optic[Void, mo.Option[A], mo.Option[A], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

Present returns a Predicate that focuses true if the option is present.

Example
data := []mo.Option[int]{
	mo.Some(1),
	mo.None[int](),
	mo.Some(2),
}

//View actions like MustToSliceOf unwrap the option if possible and ignore the None elements.
var result []bool = MustGet(
	SliceOf(
		Compose(
			TraverseSlice[mo.Option[int]](),
			Present[int](),
		),
		len(data)),
	data,
)
fmt.Println(result)
Output:

[true false true]

func Prism

func Prism[S, A any](
	match func(source S) (A, bool),
	embed func(focus A) S,
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnMany, ReadWrite, BiDir, Pure]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns the match or false.
  • embed : converts the focus to the source type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

Example
//This prism converts an any to a string
//the Cast function implements a generic version of this example
anyToString := Prism[any, string](
	func(source any) (string, bool) {
		str, ok := source.(string)
		return str, ok
	},
	func(focus string) any {
		return focus
	},
	ExprCustom("ExamplePrism"),
)

var str string
var isMatch bool
str, isMatch = MustGetFirst(anyToString, "Lorem ipsum")
fmt.Println(str, isMatch)

str, isMatch = MustGetFirst(anyToString, nil)
fmt.Println(isMatch)

//If the given value is a string then convert it to upper case
var resStr any = MustModify(anyToString, Op(strings.ToUpper), "Lorem ipsum")
fmt.Println(resStr)

//If the value is not a string the the prism returns the original value back
var resInt any = MustModify(anyToString, Op(strings.ToUpper), 1)
fmt.Println(resInt)
Output:

Lorem ipsum true
false
LOREM IPSUM
1

func PrismE

func PrismE[S, A any](
	match func(ctx context.Context, source S) (A, bool, error),
	embed func(ctx context.Context, focus A) (S, error),
	exprDef ExpressionDef,
) Optic[Void, S, S, A, A, ReturnMany, ReadWrite, BiDir, Err]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns the match or false.
  • embed : converts the focus to the source type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

Example
//This prism umarshals json and only focuses on json objects
//other json types (string,array,number) are ignored
//Json parse errors are returned
jsonPrism := PrismE[string, map[string]any](
	func(ctx context.Context, source string) (map[string]any, bool, error) {
		var a any
		err := json.Unmarshal([]byte(source), &a)
		if err != nil {
			return nil, true, err
		}

		switch t := a.(type) {
		case map[string]any:
			return t, true, nil
		default:
			return nil, false, nil
		}
	},
	func(ctx context.Context, focus map[string]any) (string, error) {
		bytes, err := json.Marshal(focus)
		return string(bytes), err
	},
	ExprCustom("ExamplePrism"),
)

var jsonObj map[string]any
var isMatch bool
jsonObj, isMatch, err := GetFirst(jsonPrism, `{"key":"value"}`)
fmt.Println(jsonObj, isMatch, err)

//Parse the json obj, Traverse over the properties, cast them to string and convert them to uppercase
var resStr string
resStr, err = Modify(
	Compose3(
		jsonPrism,
		TraverseMap[string, any](),
		DownCast[any, string](),
	),
	Op(strings.ToUpper),
	`{"key":"value"}`,
)
fmt.Println(resStr, err)

//If the value is valid json but is not a json obj then the prism returns the original value back
resStr, err = Modify(
	Compose3(
		jsonPrism,
		TraverseMap[string, any](),
		DownCast[any, string](),
	),
	Op(strings.ToUpper),
	`1`,
)
fmt.Println(resStr, err)

//If the source is invalid json then an error is returned
_, err = Modify(
	Compose3(
		jsonPrism,
		TraverseMap[string, any](),
		DownCast[any, string](),
	),
	Op(strings.ToUpper),
	`invalid json`,
)
fmt.Println(err)

//If the source is valid but we create an invalid json object then the marshal error is returned
_, err = Set(
	Compose(
		jsonPrism,
		TraverseMap[string, any](),
	),
	any(func() {}),
	`{"key":"value"}`,
)
fmt.Println(err)
Output:

map[key:value] true <nil>
{"key":"VALUE"} <nil>
1 <nil>
invalid character 'i' looking for beginning of value
optic error path:
	Custom(ExamplePrism)

json: unsupported type: func()
optic error path:
	Custom(ExamplePrism)

func PrismEP

func PrismEP[S, T, A, B any](
	match func(ctx context.Context, source S) (mo.Either[T, A], error),
	embed func(ctx context.Context, focus B) (T, error),
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnMany, ReadWrite, BiDir, Err]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns either the polymorphic result type or the matched value.
  • embed : converts the focus to the result type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

func PrismI

func PrismI[I, S, A any](
	match func(source S) (I, A, bool),
	embed func(focus A) S,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadWrite, BiDir, Pure]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns the match or false.
  • embed : converts the focus to the source type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

func PrismIE

func PrismIE[I, S, A any](
	match func(ctx context.Context, source S) (I, A, bool, error),
	embed func(ctx context.Context, focus A) (S, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadWrite, BiDir, Err]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns the match or false.
  • embed : converts the focus to the source type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

func PrismIEP

func PrismIEP[I, S, T, A, B any](
	match func(ctx context.Context, source S) (mo.Either[T, ValueI[I, A]], error),
	embed func(ctx context.Context, focus B) (T, error),
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnMany, ReadWrite, BiDir, Err]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns either the polymorphic result type or the matched value.
  • embed : converts the focus to the result type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

Example
//This is a rather contrived example.
//This Prism unmarshals a json string and casts it to a map[string]any
//other json types (string,array,number) are ignored
//Json parse errors are returned
//Under modification the prism expects a string instead of a map[string]any
//And returns an []byte instead of a string.
jsonPrism := PrismIEP[Void, string, []byte, map[string]any, string](
	func(ctx context.Context, source string) (mo.Either[[]byte, ValueI[Void, map[string]any]], error) {
		var a any
		err := json.Unmarshal([]byte(source), &a)
		if err != nil {
			return mo.Left[[]byte, ValueI[Void, map[string]any]]([]byte(source)), err
		}

		switch t := a.(type) {
		case map[string]any:
			return mo.Right[[]byte, ValueI[Void, map[string]any]](ValI(Void{}, t)), nil
		default:
			return mo.Left[[]byte, ValueI[Void, map[string]any]]([]byte(source)), err
		}
	},
	func(ctx context.Context, focus string) ([]byte, error) {
		bytes, err := json.Marshal(focus)
		return bytes, err
	},
	IxMatchVoid(),
	ExprCustom("ExamplePrism"),
)

var jsonObj map[string]any
var isMatch bool
jsonObj, isMatch, err := GetFirst(jsonPrism, `{"key":"value"}`)
fmt.Println(jsonObj, isMatch, err)

var resStr []byte
resStr, err = Modify( //return type is []byte
	jsonPrism,
	Op(func(focus map[string]any) string { //convert from map to string
		return fmt.Sprint(focus)
	}),
	`{"key":"value"}`, //String input
)

//The result is a byte array containing the go string representation of a map embedded inside a json string.....
fmt.Println(string(resStr), err)
Output:

map[key:value] true <nil>
"map[key:value]" <nil>

func PrismIP

func PrismIP[I, S, T, A, B any](
	match func(source S) mo.Either[T, ValueI[I, A]],
	embed func(focus B) T,
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnMany, ReadWrite, BiDir, Pure]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns either the polymorphic result type or the matched value.
  • embed : converts the focus to the result type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

func PrismP

func PrismP[S, T, A, B any](
	match func(source S) mo.Either[T, A],
	embed func(focus B) T,
	exprDef ExpressionDef,
) Optic[Void, S, T, A, B, ReturnMany, ReadWrite, BiDir, Pure]

Constructor for a Prism optic. Prisms focus on zero or 1 element.

The following Traversal constructors are available.

A prism is constructed from 3 functions

  • match : performs a pattern match and returns either the polymorphic result type or the matched value.
  • embed : converts the focus to the result type. This is equivalent to a ReverseGetterFunc
  • expr: should return the expression type. See the expr package for more information.

When traversed the prism will return no focuses if the match fails. When modified the prism will return the original source if the match fails.

Example
//This prism converts an any to a string and an int to an any
//the CastP function implements a generic version of this example
anyToString := PrismP[any, any, string, int](
	func(source any) mo.Either[any, string] {
		if str, ok := source.(string); ok {
			return mo.Right[any, string](str)
		} else {
			return mo.Left[any, string](source)
		}

	},
	func(focus int) any {
		return focus
	},
	ExprCustom("ExamplePrism"),
)

var str string
var isMatch bool
str, isMatch = MustGetFirst(anyToString, "Lorem ipsum")
fmt.Println(str, isMatch)

//If the given value is a string then parse it and multiply it by 2
var resStr any
resStr, err := Modify(Compose(anyToString, ParseIntP[int](10, 32)), Mul(2), "100")
fmt.Printf("%v : %T : %v\n", resStr, resStr, err)

//If the value is not a string the the prism returns the original value back
var resInt any
resInt, err = Modify(Compose(anyToString, ParseIntP[int](10, 32)), Mul(2), true)
fmt.Printf("%v : %T : %v\n", resInt, resInt, err)
Output:

Lorem ipsum true
200 : int : <nil>
true : bool : <nil>

func PtrFieldLens

func PtrFieldLens[S, A any](fref func(source *S) *A) Optic[Void, *S, *S, A, A, ReturnMany, ReadWrite, UniDir, Pure]

PtrFieldLens returns a Traversal focusing on a field within a pointer to a struct. If the source pointer is nil then nothing is focused.

A PtrFieldLens is constructed from a single function - fref: should return the address of the field within the given struct.

Note: PtrFieldLenses are normally created by the makelens tool which also provides a convenient composition builder.

See: - FieldLens for a lens that focuses on a value of the source. - PtrFieldLensE for a lens that focuses on a pointer of the source where the source is not expected to be nil.

Example
package main

import (
	"fmt"
	"strings"

	. "github.com/spearson78/go-optic"
)

type PtrPerson struct {
	Name    string
	Age     int `example:"age"`
	Hobbies []string
}

func main() {

	nameField := PtrFieldLens(func(source *Person) *string { return &source.Name })
	ageField := PtrFieldLens(func(source *Person) *int { return &source.Age })
	hobbiesField := PtrFieldLens(func(source *Person) *[]string { return &source.Hobbies })

	data := &Person{
		Name:    "Max Mustermann",
		Age:     46,
		Hobbies: []string{"eating", "sleeping"},
	}

	name, _ := MustGetFirst(nameField, data)
	age, _ := MustGetFirst(ageField, data)
	hobbies, _ := MustGetFirst(hobbiesField, data)

	fmt.Println(name, age, hobbies)

	olderPerson := MustSet(ageField, 47, data)
	fmt.Println(olderPerson)

	//Note: the return type is a person with hobbies converted to upper case
	var upperHobbies *Person = MustModify(Compose(hobbiesField, TraverseSlice[string]()), Op(strings.ToUpper), data)
	fmt.Println(upperHobbies)

}
Output:

Max Mustermann 46 [eating sleeping]
&{Max Mustermann 47 [eating sleeping]}
&{Max Mustermann 46 [EATING SLEEPING]}

func PtrFieldLensE

func PtrFieldLensE[S, A any](fref func(source *S) *A) Optic[Void, *S, *S, A, A, ReturnOne, ReadWrite, UniDir, Err]

PtrFieldLensE returns a Lens focusing on a field within a pointer to a struct. If the source pointer is nil then ErrNilPointer is returned.

A PtrFieldLensE is constructed from a single function - fref: should return the address of the field within the given struct.

See: - FieldLens for a lens that focuses on a value of the source. - PtrFieldLens for a lens that focuses on a pointer of the source but ignores nil sources.

Example
package main

import (
	"fmt"
)

type Tree struct {
	Value    string
	Children []*Tree
}

func (t *Tree) String() string {
	return fmt.Sprintf("{%v [%v]}", t.Value, t.Children)
}

func main() {

	childrenField := PtrFieldLensE(func(source *Tree) *[]*Tree { return &source.Children })
	childrenTraversal := Compose(childrenField, TraverseSlice[*Tree]())

	data := &Tree{
		Value: "root",
		Children: []*Tree{
			&Tree{
				Value: "root/first",
			},
			&Tree{
				Value: "root/second",
			},
		},
	}

	var found bool
	var firstChild *Tree
	firstChild, found, err := GetFirst(Index(childrenTraversal, 0), data)
	fmt.Println(firstChild, found, err)

	//Note: a new root node is returned with the new child node
	var addChild *Tree
	addChild, err = Modify(childrenField, AppendSlice(ValCol(&Tree{Value: "root/third"})), data)
	fmt.Println(addChild, err)

	//The original tree has not been modified.
	fmt.Println(data)

}
Output:

{root/first [[]]} true <nil>
{root [[{root/first [[]]} {root/second [[]]} {root/third [[]]}]]} <nil>
{root [[{root/first [[]]} {root/second [[]]}]]}

func PtrOption

func PtrOption[A any]() Optic[Void, *A, *A, mo.Option[A], mo.Option[A], ReturnOne, ReadWrite, BiDir, Pure]

PtrOption returns a Iso that converts a pointer into a mo.Option. Nil is converted to the None option.

See:

Example
one, three := 1, 3

data := []*int{
	&one,
	nil,
	&three,
}

optic := Compose(TraverseSlice[*int](), PtrOption[int]())

//View actions like MustListOf convert the none elements to the default value
var results []mo.Option[int] = MustGet(SliceOf(optic, len(data)), data)
fmt.Println(results)

//Some filters out the None values and allows us to operate on the populate values
var overResult []*int = MustModify(Compose(optic, Some[int]()), Mul(10), data)
fmt.Println(*overResult[0], overResult[1], *overResult[2])
Output:

[{true 1} {false 0} {true 3}]
10 <nil> 30

func PtrOptionP

func PtrOptionP[A, B any]() Optic[Void, *A, *B, mo.Option[A], mo.Option[B], ReturnOne, ReadWrite, BiDir, Pure]

PtrOptionP returns a polymorphic Iso that converts a pointer into a mo.Option. Nil is converted to the None option.

See:

func ReIndexed

func ReIndexed[I, J, K, S, T, A, B, RET, RW, DIR, ERR any, RETI TReturnOne, RWI any, DIRI any, ERRI any, ERRP TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], ixmap Optic[K, I, I, J, J, RETI, RWI, DIRI, ERRI], ixMatch Predicate[lo.Tuple2[J, J], ERRP]) Optic[J, S, T, A, B, RET, RW, DIR, CompositionTree[ERR, ERRI]]

The ReIndexed combinator returns an optic where the index is replaced with an arbitrarily mapped value. The ixmap should ideally be an Iso to enable the [AsIndex] combinator to operate efficiently.

Note: multiple values may share the same index.

See Indexing for a version that replaces the index with an integer position.

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := ReIndexed(
	TraverseMap[string, int](),
	Op(func(index string) int {
		return len(index)
	}),
	EqT2[int](),
)

//Focus on elements with an index > 4 where the index is now the string length of the key
viewResult := MustGet(SliceOf(WithIndex(Indices(optic, Gt(4))), 4), data)
fmt.Println(viewResult)

//Focus on elements with an index > 4 where the index is now the string length of the key
var modifyResult map[string]int = MustModify(Indices(optic, Gt(4)), Mul(10), data)
fmt.Println(modifyResult)
Output:

[5:1 5:4 5:3]
map[alpha:10 beta:2 delta:40 gamma:30]

func ReIndexedCol

func ReIndexedCol[A any, I, J comparable, L any, IRET TReturnOne, IRW any, IDIR any, IERR TPure](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, IERR]) Optic[Void, Collection[I, A, Pure], Collection[I, A, Pure], Collection[J, A, Pure], Collection[J, A, Pure], ReturnOne, CompositionTree[IRW, IDIR], IDIR, Pure]

The ReIndexedCol combinator focuses on a Collection where the comparable index has been remapped using the ixmap optic.

See:

Example
data := ValCol("alpha", "beta", "gamma", "delta")

optic := ReIndexedCol[string](Add(1))

getRes := MustGet(optic, data)
fmt.Println(getRes)

modifyRes := MustModify(
	optic,
	FilteredColI(
		OpOnIx[string](
			Odd[int](),
		),
		IxMatchComparable[int](),
	),
	data,
)
fmt.Println(modifyRes)
Output:

Col[1:alpha 2:beta 3:gamma 4:delta]
Col[0:alpha 2:gamma]

func ReIndexedColI

func ReIndexedColI[A, I, J, L any, IRET TReturnOne, IRW any, IDIR any, IERR, MIERR, MJERR TPure](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, IERR], ixmatchi Predicate[lo.Tuple2[I, I], MIERR], ixmatchj Predicate[lo.Tuple2[J, J], MJERR]) Optic[Void, Collection[I, A, Pure], Collection[I, A, Pure], Collection[J, A, Pure], Collection[J, A, Pure], ReturnOne, CompositionTree[IRW, IDIR], IDIR, Pure]

The ReIndexedColI combinator focuses on a Collection where the index has been remapped using the ixmap optic.

See:

  • ReIndexedCol for a simpler version that supports only comparable indices
  • ReIndexedColP for a polymorphic version that supports only comparable indices
  • ReIndexedColIP for a polymorphic version, non comparable index version.
Example
data := ValCol("alpha", "beta", "gamma", "delta")

optic := ReIndexedColI[string](
	Compose(
		FirstOrDefault(Ignore(AsReverseGet(ParseInt[int](10, 0)), True[error]()), ""),
		PrependString(StringCol("index_")),
	),
	EqT2[int](),
	EqT2[string](),
)

getRes := MustGet(optic, data)
fmt.Println(getRes)
Output:

Col[index_0:alpha index_1:beta index_2:gamma index_3:delta]

func ReIndexedColIP

func ReIndexedColIP[A, B, I, J, L any, IRET TReturnOne, IRW any, IDIR any, IERR, MIERR, MJERR TPure](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, IERR], ixmatchi Predicate[lo.Tuple2[I, I], MIERR], ixmatchj Predicate[lo.Tuple2[J, J], MJERR]) Optic[Void, Collection[I, A, Pure], Collection[I, B, Pure], Collection[J, A, Pure], Collection[J, B, Pure], ReturnOne, CompositionTree[IRW, IDIR], IDIR, Pure]

The ReIndexedColIP polymorphic combinator focuses on a Collection where the index has been remapped using the ixmap optic.

See:

func ReIndexedColP

func ReIndexedColP[A, B any, I, J comparable, L any, IRET TReturnOne, IRW any, IDIR any, IERR TPure](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, IERR]) Optic[Void, Collection[I, A, Pure], Collection[I, B, Pure], Collection[J, A, Pure], Collection[J, B, Pure], ReturnOne, CompositionTree[IRW, IDIR], IDIR, Pure]

The ReIndexedColP polymorphic combinator focuses on a Collection where the index has been remapped using the ixmap optic.

See:

  • ReIndexedCol for a non polymorphic version
  • ReIndexedColI for a non polymorphic version that supports non comparable indices
  • ReIndexedColIP for a polymorphic version, non comparable index version.

func Reduce

func Reduce[I, S, T, A, B, RET, RW, DIR, ERR, SA, RA, ERRREDUCE any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], m ReductionP[SA, A, RA, ERRREDUCE]) Optic[Void, S, S, RA, RA, RET, ReadOnly, UniDir, CompositionTree[ERR, ERRREDUCE]]

The Reduce combinator returns an Iteration that focuses the result of applying the Reducer to the given optic.

If the given optic is empty then no reduced value is focused.

Example
data := []int{1, 2, 3, 4}

sum, ok := MustGetFirst(Reduce(TraverseSlice[int](), Sum[int]()), data)

fmt.Println(sum, ok)
Output:

10 true

func Ret1

func Ret1[I, S, T, A, B any, RET TReturnOne, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, ReturnOne, RW, DIR, ERR]

The Ret1 re-constrain converts an Optic with a complex but ReturnOne return type to ReturnOne

RET TReturnOne --> ReturnOne

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	T2B[int, string](),
	ParseInt[int](10, 32),
)

var reconstrained Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	ReturnOne,
	ReadWrite,
	UniDir,
	Err,
] = Ret1(Rw(Ud(EErr(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Lens

func RetL

func RetL[I, S, T, A, B any, RETL any, RETR TReturnOne, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RETL, RETR], RW, DIR, ERR]) Optic[I, S, T, A, B, RETL, RW, DIR, ERR]

The RetL re-constrain converts an Optic's return type to the left side of the CompositionTree where the right side is ReturnOne.

CompositionTree[RETL any, RETR TReturnOne] --> RETL

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticM Optic[
	Void,
	[]string,
	[]string,
	int,
	int,
	CompositionTree[ReturnMany, ReturnOne], //Note ReturnMany on the left
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	TraverseSlice[string](),
	ParseInt[int](10, 32),
)

var reconstrainedM Optic[
	Void,
	[]string,
	[]string,
	int,
	int,
	ReturnMany, //RetL reconstrained as ReturnMany
	ReadWrite,
	UniDir,
	Err,
] = RetL(Rw(Ud(EErr(opticM))))

fmt.Println(reconstrainedM.OpticType())

var optic1 Optic[
	Void,
	[]byte,
	[]byte,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne], //Note the ReturnOne on the left
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	IsoCast[[]byte, string](),
	ParseInt[int](10, 32),
)

var reconstrained1 Optic[
	Void,
	[]byte,
	[]byte,
	int,
	int,
	ReturnOne, //RetL reconstrained as ReturnOne
	ReadWrite,
	BiDir,
	Err,
] = RetL(Rw(Bd(EErr(optic1))))

fmt.Println(reconstrained1.OpticType())
Output:

Traversal
Iso

func RetM

func RetM[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, ReturnMany, RW, DIR, ERR]

The RetM re-constrain converts an Optic with any return type to ReturnMany

RET any --> ReturnMany

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	[]string,
	[]string,
	int,
	int,
	CompositionTree[ReturnMany, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	TraverseSlice[string](),
	ParseInt[int](10, 32),
)

var reconstrained Optic[
	Void,
	[]string,
	[]string,
	int,
	int,
	ReturnMany,
	ReadWrite,
	UniDir,
	Err,
] = RetM(Rw(Ud(EErr(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Traversal

func RetMerge

func RetMerge[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RET, RET], RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The RetMerge re-constrain combines identical left and right side return types of a composition tree..

CompositionTree[RET, RET] --> RET

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetMergeL

func RetMergeL[I, S, T, A, B any, RET1 any, RET2 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET1], RET2], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[RET1, RET2], RW, DIR, ERR]

The RetMergeL re-constrain combines identical left and right side of the left side of a nested {CompositionTree]

CompositionTree[CompositionTree[RET1, RET1], RET2] --> CompositionTree[RET1, RET2]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetMergeR

func RetMergeR[I, S, T, A, B any, RET1 any, RET2 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RET1, CompositionTree[RET2, RET2]], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[RET1, RET2], RW, DIR, ERR]

The RetMergeR re-constrain combines identical left and right side of the right side of a nested {CompositionTree]

CompositionTree[RET1, CompositionTree[RET2, RET2]] --> CompositionTree[RET1, RET2]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetR

func RetR[I, S, T, A, B any, RETL TReturnOne, RETR any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RETL, RETR], RW, DIR, ERR]) Optic[I, S, T, A, B, RETR, RW, DIR, ERR]

The RetR re-constrain converts an Optic's return type to the right side of the CompositionTree where the left side is ReturnOne.

CompositionTree[RETL TReturnOne, RETR any] --> RETR

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticM Optic[
	int,
	[]byte,
	[]byte,
	rune,
	rune,
	CompositionTree[ReturnOne, ReturnMany], //Note ReturnMany on the right
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, UniDir],
	CompositionTree[Pure, Pure],
] = Compose(
	IsoCast[[]byte, string](),
	TraverseString(),
)

var reconstrainedM Optic[
	int,
	[]byte,
	[]byte,
	rune,
	rune,
	ReturnMany, //RetL reconstrained as ReturnMany
	ReadWrite,
	UniDir,
	Err,
] = RetR(Rw(Ud(EErr(opticM))))

fmt.Println(reconstrainedM.OpticType())

var optic1 Optic[
	Void,
	[]byte,
	[]byte,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne], //Note the ReturnOne on the right
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	IsoCast[[]byte, string](),
	ParseInt[int](10, 32),
)

var reconstrained1 Optic[
	Void,
	[]byte,
	[]byte,
	int,
	int,
	ReturnOne, //RetR reconstrained as ReturnOne
	ReadWrite,
	BiDir,
	Err,
] = RetR(Rw(Bd(EErr(optic1))))

fmt.Println(reconstrained1.OpticType())
Output:

Traversal
Iso

func RetSwap

func RetSwap[I, S, T, A, B any, RETL any, RETR any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RETL, RETR], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[RETR, RETL], RW, DIR, ERR]

The RetSwap re-constrain swaps the left and right side of an Optic's return type CompositionTree.

CompositionTree[RETL, RETR] --> CompositionTree[RETR, RETL]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetSwapL

func RetSwapL[I, S, T, A, B any, RET1 any, RET2 any, RET3 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], RET3], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET2, RET1], RET3], RW, DIR, ERR]

The RetSwapL re-constrain swaps the left and right side of the left side of a nested CompositionTree.

CompositionTree[CompositionTree[RET1, RET2], RET3] --> CompositionTree[CompositionTree[RET2, RET1], RET3]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetSwapR

func RetSwapR[I, S, T, A, B any, RET1 any, RET2 any, RET3 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RET1, CompositionTree[RET2, RET3]], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[RET1, CompositionTree[RET3, RET2]], RW, DIR, ERR]

The RetSwapR re-constrain swaps the left and right side of the right side of a nested CompositionTree.

CompositionTree[RET1, CompositionTree[RET2, RET3]] --> CompositionTree[RET1, CompositionTree[RET3, RET2]]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetTrans

func RetTrans[I, S, T, A, B any, RET1 any, RET2 any, RET3 any, RET4 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], CompositionTree[RET3, RET4]], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET3], CompositionTree[RET2, RET4]], RW, DIR, ERR]

The RetTrans re-constrain transposes the middle return type of a nested CompositionTree.

CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4] --> CompositionTree[CompositionTree[ERR1, ERR3], CompositionTree[ERR2, ERR4]

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetTransL

func RetTransL[I, S, T, A, B any, RET1 any, RET2 any, RET3 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], RET3], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET3], RET2], RW, DIR, ERR]

The RetTransL re-constrain transposes the right element with the right child of a nested composition tree to the left.

CompositionTree[CompositionTree[RET1, RET2], RET3] --> CompositionTree[CompositionTree[RET1, RET3], RET2] This has the effect of removing a level of nested from the RET2 path of the composition tree.

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RetTransR

func RetTransR[I, S, T, A, B any, RET1 any, RET2 any, RET3 any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, CompositionTree[RET1, CompositionTree[RET2, RET3]], RW, DIR, ERR]) Optic[I, S, T, A, B, CompositionTree[RET2, CompositionTree[RET1, RET3]], RW, DIR, ERR]

The RetTransR re-constrain transposes the left element with the left child of a nested composition tree to the right.

CompositionTree[RET1, CompositionTree[RET2, RET3]] --> CompositionTree[RET2, CompositionTree[RET1, RET3]] This has the effect of removing a level of nested from the RET2 path of the composition tree.

See:

  • Ret1 for a re-constrain to ReturnOne
  • RetM for a re-constrain to ReturnMany
  • RetL for a re-constrain to the left side of a CompositionTree
  • RetR for a re-constrain to the Right side of a CompositionTree
  • RetSwap for a re-constrain that swaps the components of a CompositionTree
  • RetSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RetSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RetMerge for a re-constrain that merges identical components of a CompositionTree
  • RetMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RetMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RetTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RetTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RetTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func Reversed

func Reversed[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, UniDir, ERR]

The Reversed combinator returns an optic that focuses on the elements in the input optic in reverse order.

Warning: the input optic is fully iterated in order to reverse the order.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

//taking 2 reversed is equivalent to taking the last 2 elements in the optic
reversedOptic := Taking(Reversed(TraverseSlice[string]()), 2)

listResult := MustGet(SliceOf(reversedOptic, len(data)), data)
fmt.Println(listResult)

//Note that the result of over is still in the original collection.
//However the last 2 elements were converted to upper case as they were focused by the optic.
overResult := MustModify(reversedOptic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[delta gamma]
[alpha beta GAMMA DELTA]

func ReversedCol

func ReversedCol[I, A any]() Optic[Void, Collection[I, A, Pure], Collection[I, A, Pure], Collection[I, A, Pure], Collection[I, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

ReversedCol returns an Iso that reverses the order of a Collection.

See: - ReversedColP for a polymorphic version - Reversed for a non collection version.

func ReversedColP

func ReversedColP[I, A, B any]() Optic[Void, Collection[I, A, Pure], Collection[I, B, Pure], Collection[I, A, Pure], Collection[I, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

ReversedColP returns an polymorphic Iso that reverses the order of an Collection.

See: - ReversedCol for a non polymorphic version - Reversed for a non collection version.

Example
slice := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}

var result []int
result, err := Get(
	SliceOfP(
		Compose4(
			SliceToColP[string, int](),
			ReversedColP[int, string, int](),
			TraverseColP[int, string, int](),
			ParseIntP[int](10, 32),
		),
		10,
	),
	slice,
)
fmt.Println(result, err)
Output:

[10 9 8 7 6 5 4 3 2 1] <nil>

func ReversedSlice

func ReversedSlice[A any]() Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, BiDir, Pure]

ReversedSlice applies the Reversed operation to a Slice

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		ReversedSlice[string](),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	ReversedSlice[string](),
	data,
)
fmt.Println(modifyRes)
Output:

[delta gamma beta alpha]
{1 [delta gamma beta alpha]}

func ReversedString

func ReversedString() Optic[Void, string, string, string, string, ReturnOne, ReadWrite, BiDir, Pure]

ReversedString applies the Reversed operation to a String

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		ReversedString(),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	ReversedString(),
	data,
)
fmt.Println(modifyRes)
Output:

tema tis rolod muspi meroL
{1 tema tis rolod muspi meroL}
func Right[A any, B any]() Optic[ChosenSide, mo.Either[A, B], mo.Either[A, B], B, B, ReturnMany, ReadWrite, BiDir, Pure]

Right returns a Prism that matches on the right element of a mo.Either

Example
left, matched := MustGetFirst(Right[int, int](), mo.Left[int, int](1))
fmt.Println(left, matched)

right, matched := MustGetFirst(Right[int, int](), mo.Right[int, int](1))
fmt.Println(right, matched)

//Setting Right on a Left value returns the original Left value
setRight := MustSet(Right[int, int](), 2, mo.Left[int, int](1))
fmt.Println(setRight)
Output:

0 false
1 true
{true 1 0}

func RightP

func RightP[A, B, C any]() Optic[ChosenSide, mo.Either[A, B], mo.Either[A, C], B, C, ReturnMany, ReadWrite, BiDir, Pure]
Example
left, matched := MustGetFirst(RightP[int, int, string](), mo.Left[int, int](1))
fmt.Println(left, matched)

right, matched := MustGetFirst(RightP[int, int, string](), mo.Right[int, int](1))
fmt.Println(right, matched)

setRight := MustModify(
	RightP[int, int, string](),
	FormatInt[int](10),
	mo.Right[int, int](1),
)
fmt.Println(setRight)
Output:

0 false
1 true
{false 0 1}

func Ro

func Ro[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, ReadOnly, UniDir, ERR]

The Ro re-constrain converts an Optic with any read/write type to ReadOnly

RW any --> ReadOnly

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	[]int,
	[]int,
	bool,
	bool,
	CompositionTree[ReturnMany, ReturnOne],
	CompositionTree[ReadWrite, ReadOnly],
	CompositionTree[UniDir, UniDir],
	CompositionTree[Pure, Pure],
] = Compose(
	TraverseSlice[int](),
	Eq(10),
)

var reconstrained Optic[
	Void,
	[]int,
	[]int,
	bool,
	bool,
	ReturnMany,
	ReadOnly,
	UniDir,
	Pure,
] = RetM(Ro(Ud(EPure(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Iteration

func Root

Root returns a Iso that returns a root of a value.

See:

  • RootOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, float64]{
	lo.T2("a", 1.0),
	lo.T2("b", 2.0),
	lo.T2("c", 3.0),
	lo.T2("d", 4.0),
	lo.T2("e", 5.0),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, float64]](), T2B[string, float64]())

//Square root of each focused value.
var overResult []lo.Tuple2[string, float64] = MustModify(optic, Root(2.0), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
var composedResult []lo.Tuple2[string, float64] = MustModify(optic, Compose(Root(2.0), Add(1.0)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Add operation in a root 2 context
//But when the result is built the value is raised by power 2 again to return it to the original context
var preComposedResult []lo.Tuple2[string, float64] = MustModify(Compose(optic, Root(2.0)), Add(1.0), data)
fmt.Println(preComposedResult)
Output:

[{a 1} {b 1.4142135623730951} {c 1.7320508075688772} {d 2} {e 2.23606797749979}]
[{a 2} {b 2.414213562373095} {c 2.732050807568877} {d 3} {e 3.23606797749979}]
[{a 4} {b 5.82842712474619} {c 7.464101615137754} {d 9} {e 10.47213595499958}]

func RootOp

func RootOp[S any, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, float64, LRET, LERR], right Operation[S, float64, RRET, RERR]) Optic[Void, S, S, float64, float64, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

RootOp returns an Operation expression that returns the right root of the left focus.

See:

  • Root for the constant version.
Example
data := []lo.Tuple2[float64, float64]{
	lo.T2(1.0, 5.0),
	lo.T2(2.0, 4.0),
	lo.T2(3.0, 3.0),
	lo.T2(4.0, 2.0),
	lo.T2(5.0, 1.0),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[float64, float64]()
rightOptic := T2B[float64, float64]()

//Create a getter that applies the Root function to the focuses of both optics
root := RootOp(leftOptic, rightOptic)

var singleValueResult float64 = MustGet(root, lo.T2(2.0, 4.0))
fmt.Println(singleValueResult) // 16

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []float64 = MustModify(TraverseSliceP[lo.Tuple2[float64, float64], float64](), root, data)
fmt.Println(overResult) // [1 16 27 16 5]
Output:

1.189207115002721
[1 1.189207115002721 1.4422495703074085 2 5]

func RootT2

RootT2 returns an BinaryOp that returns root B of A.

See:

  • Root for a unary version.
  • RootOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[float64, float64]{
	lo.T2(5.0, 2.0),
	lo.T2(6.0, 2.0),
	lo.T2(5.0, 3.0),
	lo.T2(6.0, 3.0),
}

optic := Compose(
	TraverseSlice[lo.Tuple2[float64, float64]](),
	RootT2(),
)

var res []float64 = MustGet(
	SliceOf(
		optic,
		4,
	),
	data,
)
fmt.Println(res)
Output:

[2.23606797749979 2.449489742783178 1.7099759466766968 1.8171205928321397]

func Rw

func Rw[I, S, T, A, B any, RET any, RW TReadWrite, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, ReadWrite, DIR, ERR]

The Rw re-constrain converts an Optic with a complex but ReadWrite read/write type to ReadWrite

RW TReadWrite --> ReadWrite

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	T2B[int, string](),
	ParseInt[int](10, 32),
)

var reconstrained Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	ReturnOne,
	ReadWrite,
	UniDir,
	Err,
] = Ret1(Rw(Ud(EErr(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Lens

func RwL

func RwL[I, S, T, A, B any, RET any, RWL any, RWR TReadWrite, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RWL, RWR], DIR, ERR]) Optic[I, S, T, A, B, RET, RWL, DIR, ERR]

The RwL re-constrain converts an Optic's read/write type to the left side of the CompositionTree where the right side is ReadWrite.

CompositionTree[RWL any, RWR TReadOnly] --> RWL

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticRo Optic[
	Void,
	int,
	int,
	bool,
	bool,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadOnly, ReadWrite], //Note the ReadOnly on the left
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Pure],
] = Compose(
	Eq(10),
	Not(),
)

var reconstrainedRo Optic[
	Void,
	int,
	int,
	bool,
	bool,
	ReturnOne,
	ReadOnly, //RwL reconstrained to ReadOnly
	UniDir,
	Pure,
] = Ret1(RwL(Ud(EPure(opticRo))))

fmt.Println(reconstrainedRo.OpticType())

var opticRw Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite], //Note the ReadWrite on the left
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Pure],
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrainedRw Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite, //RwL reconstrained to ReadWrite
	BiDir,
	Pure,
] = Ret1(RwL(Bd(EPure(opticRw))))

fmt.Println(reconstrainedRw.OpticType())
Output:

Getter
Iso

func RwMerge

func RwMerge[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RW, RW], DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The RwMerge re-constrain combines identical left and right side read/write types of a composition tree..

CompositionTree[RW, RW] --> RW

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwMergeL

func RwMergeL[I, S, T, A, B any, RET any, RW1 any, RW2 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW1], RW2], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[RW1, RW2], DIR, ERR]

The RwMergeL re-constrain combines identical left and right side of the left side of a nested {CompositionTree]

CompositionTree[CompositionTree[RW1, RW1], RW2] --> CompositionTree[RW1, RW2]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwMergeR

func RwMergeR[I, S, T, A, B any, RET any, RW1 any, RW2 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RW1, CompositionTree[RW2, RW2]], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[RW1, RW2], DIR, ERR]

The RwMergeR re-constrain combines identical left and right side of the right side of a nested {CompositionTree]

CompositionTree[RW1, CompositionTree[RW2, RW2]] --> CompositionTree[RW1, RW2]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwR

func RwR[I, S, T, A, B any, RET any, RWL TReadWrite, RWR any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RWL, RWR], DIR, ERR]) Optic[I, S, T, A, B, RET, RWR, DIR, ERR]

The RwR re-constrain converts an Optic's read/write type to the right side of the CompositionTree where the left side is ReadWrite.

CompositionTree[RWL TReadWrite, RWR any] --> RWR

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var opticRo Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadOnly], //Note the ReadOnly on the right
	CompositionTree[BiDir, UniDir],
	CompositionTree[Pure, Pure],
] = Compose(
	Mul(10),
	Mod(3),
)

var reconstrainedRo Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadOnly, //RwR reconstrained to ReadOnly
	UniDir,
	Pure,
] = Ret1(RwR(Ud(EPure(opticRo))))

fmt.Println(reconstrainedRo.OpticType())

var opticRw Optic[
	Void,
	int,
	int,
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite], //Note the ReadWrite on the right
	CompositionTree[BiDir, BiDir],
	CompositionTree[Pure, Pure],
] = Compose(
	Add(10),
	Mul(2),
)

var reconstrainedRw Optic[
	Void,
	int,
	int,
	int,
	int,
	ReturnOne,
	ReadWrite, //RwL reconstrained to ReadWrite
	BiDir,
	Pure,
] = Ret1(RwR(Bd(EPure(opticRw))))

fmt.Println(reconstrainedRw.OpticType())
Output:

Getter
Iso

func RwSwap

func RwSwap[I, S, T, A, B any, RET any, RWL any, RWR any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RWL, RWR], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[RWR, RWL], DIR, ERR]

The RwSwap re-constrain swaps the left and right side of an Optic's read/write type CompositionTree.

CompositionTree[RWL, RWR] --> CompositionTree[RWR, RWL]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwSwapL

func RwSwapL[I, S, T, A, B any, RET any, RW1 any, RW2 any, RW3 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW2], RW3], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW2, RW1], RW3], DIR, ERR]

The RwSwapL re-constrain swaps the left and right side of the left side of a nested CompositionTree.

CompositionTree[CompositionTree[RW1, RW2], RW3] --> CompositionTree[CompositionTree[RW2, RW1], RW3]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwSwapR

func RwSwapR[I, S, T, A, B any, RET any, RW1 any, RW2 any, RW3 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RW1, CompositionTree[RW2, RW3]], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[RW1, CompositionTree[RW3, RW2]], DIR, ERR]

The RwSwapR re-constrain swaps the left and right side of the right side of a nested CompositionTree.

CompositionTree[RW1, CompositionTree[RW2, RW3]] --> CompositionTree[RW1, CompositionTree[RW3, RW2]]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwTrans

func RwTrans[I, S, T, A, B any, RET any, RW1 any, RW2 any, RW3 any, RW4 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW2], CompositionTree[RW3, RW4]], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW3], CompositionTree[RW2, RW4]], DIR, ERR]

The RwTrans re-constrain transposes the middle read/write type of a nested CompositionTree.

CompositionTree[CompositionTree[ERR1, ERR2], CompositionTree[ERR3, ERR4] --> CompositionTree[CompositionTree[ERR1, ERR3], CompositionTree[ERR2, ERR4]

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwTransL

func RwTransL[I, S, T, A, B any, RET any, RW1 any, RW2 any, RW3 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW2], RW3], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[CompositionTree[RW1, RW3], RW2], DIR, ERR]

The RwTransL re-constrain transposes the right element with the right child of a nested composition tree to the left.

CompositionTree[CompositionTree[RW1, RW2], RW3] --> CompositionTree[CompositionTree[RW1, RW3], RW2] This has the effect of removing a level of nested from the RW2 path of the composition tree.

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func RwTransR

func RwTransR[I, S, T, A, B any, RET any, RW1 any, RW2 any, RW3 any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, CompositionTree[RW1, CompositionTree[RW2, RW3]], DIR, ERR]) Optic[I, S, T, A, B, RET, CompositionTree[RW2, CompositionTree[RW1, RW3]], DIR, ERR]

The RwTransR re-constrain transposes the left element with the left child of a nested composition tree to the right.

CompositionTree[RW1, CompositionTree[RW2, RW3]] --> CompositionTree[RW2, CompositionTree[RW1, RW3]] This has the effect of removing a level of nested from the RW2 path of the composition tree.

See:

  • Ro for a re-constrain to ReadOnly
  • Rw for a re-constrain to ReadWrite
  • RwL for a re-constrain to the left side of a CompositionTree
  • RwR for a re-constrain to the Right side of a CompositionTree
  • RwSwap for a re-constrain that swaps the components of a CompositionTree
  • RwSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • RwSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • RwMerge for a re-constrain that merges identical components of a CompositionTree
  • RwMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • RwTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • RwTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • RwTransR for a re-constrain that swaps the left components into the right nested CompositionTree

func SelfIndex

func SelfIndex[I, S, T, A, B, RET, RW, DIR, ERR any, ERRP TPure](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], ixMatch Predicate[lo.Tuple2[A, A], ERRP]) Optic[A, S, T, A, B, RET, RW, DIR, ERR]

The SelfIndex combinator replaces the index of the given optic with the source value.

See ReIndexed for a version that replaces the index with an arbitrary value.

Example
data := map[string]lo.Tuple2[int, int]{
	"alpha": lo.T2(1, 2),
	"beta":  lo.T2(3, 4),
	"gamma": lo.T2(5, 6),
	"delta": lo.T2(7, 8),
}

//This optic focuses on the second element of the tuple but makes the whole tuple available in the index.
optic := ComposeLeft(
	SelfIndex(
		TraverseMap[string, lo.Tuple2[int, int]](),
		EqDeepT2[lo.Tuple2[int, int]](),
	), T2B[int, int]())

viewResult := MustGet(SliceOf(WithIndex(optic), 4), data)
fmt.Println(viewResult)

var modifyResult map[string]lo.Tuple2[int, int] = MustModifyI(optic, OpI(func(index lo.Tuple2[int, int], focus int) int {
	return index.A + index.B
}), data)
fmt.Println(modifyResult)
Output:

[{1 2}:2 {3 4}:4 {7 8}:8 {5 6}:6]
map[alpha:{1 3} beta:{3 7} delta:{7 15} gamma:{5 11}]

func SeqEOf

func SeqEOf[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqE[A], SeqE[A], ReturnOne, RW, UniDir, ERR]

The SeqEOf combinator focuses on a iter.Seq2 of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements the result will use values from the original source. If the modified seq contains more elements they will be ignored.

See:

  • SeqEOfP for a polymorphic version.
  • [ISeqOf] for an indexed version.
  • SeqIEOf for a SeqIE version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := SeqEOf(TraverseMap[int, string]())

viewResult, err := Get(optic, data)
if err != nil {
	log.Fatal(err)
}

for val := range viewResult {
	v, err := val.Get()
	fmt.Printf("%v:%v ", v, err)
}
fmt.Println(".")

modifyResult, err := Modify(optic, Op(func(focus SeqE[string]) SeqE[string] {
	return func(yield func(ValueE[string]) bool) {
		focus(func(val ValueE[string]) bool {
			return yield(ValE(strings.ToUpper(val.Value()), val.Error()))
		})
	}
}), data)
fmt.Println(modifyResult, err)
Output:

alpha:<nil> beta:<nil> gamma:<nil> delta:<nil> .
map[1:ALPHA 2:BETA 3:GAMMA 4:DELTA] <nil>

func SeqEOfP

func SeqEOfP[I, S, T, A, B, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqE[A], SeqE[B], ReturnOne, RW, UniDir, Err]

The SeqEOfP combinator focuses on a polymorphic iter.Seq2 of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements then ErrUnsafeMissingElement will be returned If the modified seq contains more elements they will be ignored.

See:

  • SeqEOf for a safe non polymorphic version.
  • [ISeqOfP] for an indexed version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := SeqEOfP(TraverseMapP[int, string, int]())

var viewResult SeqE[string]
var err error
viewResult, err = Get(optic, data)
if err != nil {
	log.Fatal(err)
}
for val := range viewResult {
	v, err := val.Get()
	fmt.Print(v, ":", err, " ")
}
fmt.Println(".")

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, Op(func(focus SeqE[string]) SeqE[int] {
	return func(yield func(ValueE[int]) bool) {
		focus(func(val ValueE[string]) bool {
			return yield(ValE(len(val.Value()), val.Error()))
		})
	}
}), data)
fmt.Println(modifyResult, err)
Output:

alpha:<nil> beta:<nil> gamma:<nil> delta:<nil> .
map[1:5 2:4 3:5 4:5] <nil>

func SeqIEOf

func SeqIEOf[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqIE[I, A], SeqIE[I, A], ReturnOne, RW, UniDir, ERR]

The SeqIEOf combinator focuses on a SeqIE of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements the result will use values from the original source. If the modified seq contains more elements they will be ignored.

See:

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := SeqIEOf(TraverseMap[int, string]())

var viewResult SeqIE[int, string] = MustGet(optic, data)
for valIE := range viewResult {
	i, v, e := valIE.Get()
	fmt.Println(i, v, e)
}

modifyResult := MustModify(optic, Op(func(focus SeqIE[int, string]) SeqIE[int, string] {
	return func(yield func(ValueIE[int, string]) bool) {
		focus(func(val ValueIE[int, string]) bool {
			index, str, err := val.Get()
			return yield(ValIE(index, strings.ToUpper(str), err))
		})
	}
}), data)
fmt.Println(modifyResult)
Output:

1 alpha <nil>
2 beta <nil>
3 gamma <nil>
4 delta <nil>
map[1:ALPHA 2:BETA 3:GAMMA 4:DELTA]

func SeqIEOfP

func SeqIEOfP[I, S, T, A, B, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqIE[I, A], SeqIE[I, B], ReturnOne, RW, UniDir, Err]

The SeqIEOfP combinator focuses on a polymorphic SeqIE of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements then ErrUnsafeMissingElement will be returned If the modified seq contains more elements they will be ignored.

See:

  • SeqIEOf for a safe non polymorphic version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := SeqIEOfP(TraverseMapP[int, string, int]())

var viewResult SeqIE[int, string]
var err error
viewResult, err = Get(optic, data)
if err != nil {
	log.Fatal(err)
}
for valIE := range viewResult {
	i, v, e := valIE.Get()
	fmt.Println(i, v, e)
}

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, Op(func(focus SeqIE[int, string]) SeqIE[int, int] {
	return func(yield func(ValueIE[int, int]) bool) {
		focus(func(val ValueIE[int, string]) bool {
			index, str, err := val.Get()
			return yield(ValIE(index, len(str), err))
		})
	}
}), data)
fmt.Println(modifyResult, err)
Output:

1 alpha <nil>
2 beta <nil>
3 gamma <nil>
4 delta <nil>
map[1:5 2:4 3:5 4:5] <nil>

func SeqIOf

func SeqIOf[I, S, T, A, RETI, RW, DIR any, ERR TPure](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqI[I, A], SeqI[I, A], ReturnOne, RW, UniDir, ERR]

The SeqIOf combinator focuses on a iter.Seq of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements the result will use values from the original source. If the modified seq contains more elements they will be ignored.

See:

  • SeqEOfP for a polymorphic version.
  • [ISeqOf] for an indexed version.
  • SeqIEOf for a SeqIE version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice.
optic := SeqIOf(TraverseSlice[string]())

for index, focus := range MustGet(optic, data) {
	fmt.Println(index, focus)
}

var modifyResult []string = MustModify(optic, Op(func(focus SeqI[int, string]) SeqI[int, string] {
	return func(yield func(int, string) bool) {
		focus(func(i int, str string) bool {
			return yield(i, strings.ToUpper(str))
		})
	}
}), data)
fmt.Println(modifyResult)
Output:

0 alpha
1 beta
2 gamma
3 delta
[ALPHA BETA GAMMA DELTA]

func SeqIOfP

func SeqIOfP[I, S, T, A, B, RETI, RW, DIR any, ERR TPure](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[Void, S, T, SeqI[I, A], SeqI[I, B], ReturnOne, RW, UniDir, Err]

The SeqIOfP combinator focuses on a iter.Seq of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements the result will use values from the original source. If the modified seq contains more elements they will be ignored.

See:

  • SeqEOfP for a polymorphic version.
  • [ISeqOf] for an indexed version.
  • SeqIEOf for a SeqIE version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := SeqIOfP(TraverseMapP[int, string, int]())

var viewResult SeqI[int, string]
var err error
viewResult, err = Get(optic, data)
if err != nil {
	log.Fatal(err)
}
fmt.Print("Result ")
for i, v := range viewResult {
	fmt.Print(i, ":", v, " ")
}
fmt.Println(".")

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, Op(func(focus SeqI[int, string]) SeqI[int, int] {
	return func(yield func(int, int) bool) {
		focus(func(index int, str string) bool {
			return yield(index, len(str))
		})
	}
}), data)
fmt.Println(modifyResult, err)
Output:

Result 1:alpha 2:beta 3:gamma 4:delta .
map[1:5 2:4 3:5 4:5] <nil>

func SeqOf

func SeqOf[I, S, T, A, RETI, RW, DIR any, ERR TPure](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR]) Optic[Void, S, T, iter.Seq[A], iter.Seq[A], ReturnOne, RW, UniDir, ERR]

The SeqOf combinator focuses on a iter.Seq of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements the result will use values from the original source. If the modified seq contains more elements they will be ignored.

See:

  • SeqEOfP for a polymorphic version.
  • [ISeqOf] for an indexed version.
  • SeqIEOf for a SeqIE version.
Example
data := []string{"alpha", "beta", "gamma", "delta"}

//This optic focuses each string in the slice.
optic := SeqOf(TraverseSlice[string]())

for focus := range MustGet(optic, data) {
	fmt.Println(focus)
}

var modifyResult []string = MustModify(optic, Op(func(focus iter.Seq[string]) iter.Seq[string] {
	return func(yield func(string) bool) {
		focus(func(str string) bool {
			return yield(strings.ToUpper(str))
		})
	}
}), data)
fmt.Println(modifyResult)
Output:

alpha
beta
gamma
delta
[ALPHA BETA GAMMA DELTA]

func SeqOfP

func SeqOfP[I, S, T, A, B, RETI, RW, DIR any, ERR TPure](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[Void, S, T, iter.Seq[A], iter.Seq[B], ReturnOne, RW, UniDir, Err]

The SeqOfP polymorphic combinator focuses on a iter.Seq of all the elements in the given optic.

Under modification this seq can be modified using standard operations and will be rebuilt into the original data structure. If the modified seq contains fewer elements then ErrUnsafeMissingElement will be returned If the modified seq contains more elements they will be ignored.

See:

  • SeqEOfP for a polymorphic version.
  • [ISeqOf] for an indexed version.
  • SeqIEOf for a SeqIE version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := SeqOfP(TraverseMapP[int, string, int]())

var viewResult iter.Seq[string]
var err error

viewResult, err = Get(optic, data)
if err != nil {
	log.Fatal(err)
}

for v := range viewResult {
	fmt.Print(v, " ")
}
fmt.Println(".")

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, Op(func(focus iter.Seq[string]) iter.Seq[int] {
	return func(yield func(int) bool) {
		focus(func(str string) bool {
			return yield(len(str))
		})
	}
}), data)
fmt.Println(modifyResult, err)
Output:

alpha beta gamma delta .
map[1:5 2:4 3:5 4:5] <nil>

func SliceOf

func SliceOf[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], size int) Optic[Void, S, T, []A, []A, ReturnOne, RW, UniDir, ERR]

The SliceOf combinator focuses on a slice of all the elements in the given optic.

Under modification this slice can be modified using standard operations and will be rebuilt into the original data structure. If the modified slice contains fewer elements the result will use values from the original source. If the modified slice contains more elements they will be ignored.

See:

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

optic := SliceOf(TraverseMap[int, string](), 10)

viewResult := MustGet(optic, data)
fmt.Println(viewResult)

modifyResult := MustModify(optic, Op(func(focus []string) []string {
	slices.Reverse(focus)
	return focus
}), data)
fmt.Println(modifyResult)
Output:

[alpha beta gamma delta]
map[1:delta 2:gamma 3:beta 4:alpha]

func SliceOfP

func SliceOfP[I, S, T, A, B, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], size int) Optic[Void, S, T, []A, []B, ReturnOne, RW, UniDir, Err]

The SliceOfP combinator focuses on a polymorphic slice of all the elements in the given optic.

Under modification this slice can be modified using standard operations and will be rebuilt into the original data structure. If the modified slice contains fewer elements then ErrUnsafeMissingElement will be returned If the modified slice contains more elements they will be ignored.

See:

  • SliceOf for a safe non polymorphic version.
Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Polymorphic map traversal with a source type of map[int]string and result type of map[int]int
optic := SliceOfP(TraverseMapP[int, string, int](), len(data))

var viewResult []string
viewResult, err := Get(optic, data)
fmt.Println(viewResult, err)

//Note the return type is map[int]int not map[int]string
var modifyResult map[int]int
modifyResult, err = Modify(optic, Op(func(focus []string) []int {
	var modified []int
	for _, str := range focus {
		modified = append(modified, len(str))
	}

	return modified
}), data)
fmt.Println(modifyResult, err)
Output:

[alpha beta gamma delta] <nil>
map[1:5 2:4 3:5 4:5] <nil>

func SliceOp

func SliceOp[A, B any, I any, RET TReturnOne, RW any, DIR, ERR any](o Optic[I, Collection[int, A, ERR], Collection[int, B, ERR], Collection[int, B, ERR], Collection[int, B, ERR], RET, RW, DIR, ERR]) Optic[I, []A, []B, []B, []B, ReturnOne, RW, DIR, ERR]

The SliceOp combinator applies the given collection operation to a Slice and focuses the modified Slice.

See:

  • [SliceTraverseOp] for a combinator that efficiently traverses the elements of the modified Slice.
  • [SliceColOp] for a combinator that focuses the modified Collection.
Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

optic := SliceOp(
	SubCol[int, string](1, -1),
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		optic,
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	optic,
	data,
)
fmt.Println(modifyRes)
Output:

[beta gamma]
{1 [beta gamma]}

func SliceTail

func SliceTail[A any]() Optic[Void, []A, []A, []A, []A, ReturnMany, ReadWrite, UniDir, Pure]

SliceTail focuses a slice containing all but the first element of the source or nothing if the slice has 0 or 1 elements.

Example
data := []string{
	"alpha",
	"beta",
	"gamma",
	"delta",
}

res, ok := MustGetFirst(
	SliceTail[string](),
	data,
)
fmt.Println(res, ok)

var modifyRes []string = MustModify(
	Compose(
		SliceTail[string](),
		TraverseSlice[string](),
	),
	Op(strings.ToUpper),
	data,
)
fmt.Println(modifyRes)
Output:

[beta gamma delta] true
[alpha BETA GAMMA DELTA]

func SliceToCol

func SliceToCol[T any]() Optic[Void, []T, []T, Collection[int, T, Pure], Collection[int, T, Pure], ReturnOne, ReadWrite, BiDir, Pure]

SliceToCol returns an Iso that converts a slice to an Collection

Example
data := lo.T2(1, []string{
	"alpha",
	"beta",
	"gamma",
	"delta",
})

//See: [FilteredSlice] for a more convenient slice filter function.
var getRes []string = MustGet(
	Compose4(
		T2B[int, []string](),
		SliceToCol[string](),
		FilteredCol[int](Ne("beta")),
		AsReverseGet(SliceToCol[string]()),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	Compose(
		T2B[int, []string](),
		SliceToCol[string](),
	),
	FilteredCol[int](Ne("beta")),
	data,
)
fmt.Println(modifyRes)
Output:

[alpha gamma delta]
{1 [alpha gamma delta]}

func SliceToColP

func SliceToColP[A, B any]() Optic[Void, []A, []B, Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

SliceToColP returns a polymorphic Iso that converts a slice to an Collection

func Some

func Some[A any]() Optic[Void, mo.Option[A], mo.Option[A], A, A, ReturnMany, ReadWrite, BiDir, Pure]

Some returns a Prism that matches on the Some value of a mo.Option. This has the effect of traversing the option ignoring None values.

This function is synonymous with TraverseOption

See:

  • SomeP for a polymorphic version
  • SomeE for an impure version
  • SomeEP for a polymorphic impure version
  • None for a version matches on the None value.
  • Non for an optic that provides default values for None values.
Example
data := []mo.Option[int]{
	mo.Some(1),
	mo.None[int](),
	mo.Some(2),
}

//View actions like MustListOf unwrap the option if possible and ignore the None elements.
var result []int = MustGet(SliceOf(Compose(TraverseSlice[mo.Option[int]](), Some[int]()), len(data)), data)
fmt.Println(result)

//Modification actions like over cause Some to skip over out the None elements and updates only the values that are present.
//The composed lense work together to return the original data structure []mo.Option[int] with the applied mapping.
var overResult []mo.Option[int] = MustModify(Compose(TraverseSlice[mo.Option[int]](), Some[int]()), Mul(10), data)
fmt.Println(overResult)
Output:

[1 2]
[{true 10} {false 0} {true 20}]

func SomeE

func SomeE[A any]() Optic[Void, mo.Option[A], mo.Option[A], A, A, ReturnOne, ReadWrite, BiDir, Err]

SomeE returns an Iso that focuses the value of a mo.Option or returns ErrOptionNone for none values.

See:

  • Some for a pure prism version.
  • SomeP for a polymorphic version
  • SomeEP for a polymorphic impure version
  • None for a version matches on the None value.
  • Non for an optic that provides default values for None values.

func SomeEP

func SomeEP[A, B any]() Optic[Void, mo.Option[A], mo.Option[B], A, B, ReturnOne, ReadWrite, BiDir, Err]

SomeEP returns a polymorphic Iso that focuses the value of a mo.Option or returns ErrOptionNone for none values.

See:

  • Some for a pure prism version.
  • SomeP for a pure polymorphic version
  • SomeE for a non polymorphic impure version
  • None for a version matches on the None value.
  • Non for an optic that provides default values for None values.

func SomeP

func SomeP[A, B any]() Optic[Void, mo.Option[A], mo.Option[B], A, B, ReturnMany, ReadWrite, BiDir, Pure]

Some returns a polymorphic Prism that matches on the Some value of a mo.Option. This has the effect of traversing the option ignoring None values.

See:

  • Some for none a polymorphic version
  • SomeE for a non polymorphic impure version
  • SomeEP for a polymorphic impure version
  • None for a version matches on the None value.
  • Non for an optic that provides default values for None values.
Example
var matchBool mo.Either[mo.Option[bool], int] = MustGet(
	Matching(
		SomeP[int, bool](),
	),
	mo.None[int](),
)
fmt.Println(matchBool.MustLeft().IsPresent())

matchBool = MustGet(
	Matching(
		SomeP[int, bool](),
	),
	mo.Some[int](1),
)
fmt.Println(matchBool.MustRight())

//Output
//false
//1

func SplitString

func SplitString(splitOn *regexp.Regexp) Optic[int, string, string, string, string, ReturnMany, ReadWrite, UniDir, Pure]

SplitString returns an Traversal that focuses on the substrings separated by the splitOn parameter.

See: - MatchString for a for a version that focuses on the match - Worded for a word splitting Traversal - Lined for line splitting Traversal

Example
data := "Lorem  Ipsum    Dolor    Sit    Amet"

splitWhitespace := SplitString(regexp.MustCompile(`\s+`))

numWords := MustGet(Length(splitWhitespace), data)
fmt.Println(numWords)

result := MustModifyI(splitWhitespace, OpI(func(index int, word string) string {
	if index%2 == 0 {
		return strings.ToUpper(word) //Convert even indexed words to uppercase
	} else {
		return strings.ToLower(word) //Convert odd indexed words to lowercase
	}

}), data)
fmt.Println(result)
Output:

5
LOREM  ipsum    DOLOR    sit    AMET

func Stop

func Stop[I, S, A, RET, RW, DIR, ERR any, PERR TPure](o Optic[I, S, S, A, A, RET, RW, DIR, ERR], stopPred Predicate[error, PERR]) Optic[I, S, S, A, A, ReturnMany, ReadOnly, UniDir, Pure]

The Stop combinator returns an optic that stops on errors that match the given predicate.

See:

  • Catch for an optic that can handle errors.
  • Ignore for an optic that ignores errors.
Example
optic := Stop(
	Compose(
		TraverseSlice[string](),
		ParseInt[int32](10, 32),
	),
	ErrorIs(strconv.ErrSyntax),
)

viewResult, err := Get(SliceOf(optic, 3), []string{"1", "two", "3"})
fmt.Println(viewResult, err)

viewResult, err = Get(SliceOf(optic, 3), []string{"1", "2147483648"})
fmt.Println(viewResult, err)
Output:

[1] <nil>
[] strconv.ParseInt: parsing "2147483648": value out of range
optic error path:
	ParseInt(10,32)
	Traverse
	Stop(Traverse | ParseInt(10,32),ErrorIs(invalid syntax))
	SliceOf(Stop(Traverse | ParseInt(10,32),ErrorIs(invalid syntax)))

func StringHasPrefix

func StringHasPrefix(prefix string) Optic[Void, string, string, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

StringHasPrefix returns an Operator that focus the result of strings.HasPrefix

Example
data := "alphabet"

res := MustGet(
	StringHasPrefix("alpha"),
	data,
)
fmt.Println(res)
Output:

true

func StringHasSuffix

func StringHasSuffix(suffix string) Optic[Void, string, string, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

StringHasSuffix returns an Operator that focus the result of strings.HasSuffix

Example
data := "alphabet"

res := MustGet(
	StringHasSuffix("bet"),
	data,
)
fmt.Println(res)
Output:

true

func StringOf

func StringOf[I, S, T, RETI, RW, DIR, ERR any](o Optic[I, S, T, rune, rune, RETI, RW, DIR, ERR], size int) Optic[Void, S, T, string, string, ReturnOne, RW, UniDir, ERR]

The StringOf combinator focuses on a string composed of the runes focused by the given optic.

Under modification this string can be modified using standard operations and will be rebuilt into the original data structure. If the modified string contains fewer runes the result will use runes from the original source. If the modified string contains more runes they will be ignored.

Example
data := map[int]rune{
	1: 'a',
	2: 'l',
	3: 'p',
	4: 'h',
	5: 'a',
}

optic := StringOf(TraverseMap[int, rune](), 10)

var viewResult string = MustGet(optic, data)
fmt.Println(viewResult)

var modifyResult map[int]rune = MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(MustModify(TraverseMapP[int, rune, string](), UpCast[rune, string](), modifyResult))
Output:

alpha
map[1:A 2:L 3:P 4:H 5:A]

func StringOp

func StringOp[I any, RET TReturnOne, RW any, DIR, ERR any](o Optic[I, Collection[int, rune, ERR], Collection[int, rune, ERR], Collection[int, rune, ERR], Collection[int, rune, ERR], RET, RW, DIR, ERR]) Optic[I, string, string, string, string, ReturnOne, RW, DIR, ERR]

The StringOp combinator applies the given collection operation to a String and focuses the modified String.

See:

  • [StringTraverseOp] for a combinator that efficiently traverses the elements of the modified String.
  • [StringColOp] for a combinator that focuses the modified Collection.
Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

optic := StringOp(FilteredCol[int](In('a', 'e', 'i', 'o', 'u', ' ')))

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		optic,
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	optic,
	data,
)
fmt.Println(modifyRes)
Output:

oe iu oo i ae
{1 oe iu oo i ae}

func StringToCol

StringToCol returns an Iso that converts a string to an Collection

Example
data := "Lorem ipsum dolor sit amet"

//See: [FilteredString] for a more convenient string filter function.
var getRes string = MustGet(
	Compose3(
		StringToCol(),
		FilteredCol[int](In('a', 'e', 'i', 'o', 'u', ' ')),
		AsReverseGet(StringToCol()),
	),
	data,
)
fmt.Println(getRes)

var modifyRes string = MustModify(
	StringToCol(),
	FilteredCol[int](In('a', 'e', 'i', 'o', 'u', ' ')),
	data,
)
fmt.Println(modifyRes)
Output:

oe iu oo i ae
oe iu oo i ae

func Sub

func Sub[A Arithmetic](right A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

Sub returns a Iso that performs a subtraction by a constant value.

See:

  • SubFrom for a version that subtracts from a constant value.
  • SubOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 11),
	lo.T2("b", 22),
	lo.T2("c", 33),
	lo.T2("d", 44),
	lo.T2("e", 55),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Sub 10 to each focused int.
var overResult []lo.Tuple2[string, int] = MustModify(optic, Sub(10), data)
fmt.Println(overResult)

//Getters are optics and can be composed.
//This composition subtracts 10 then multiplies by 2
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(Sub(10), Mul(2)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Mul operation in a subtract 10 context
//But when the result is built the value is added by 10 again to return it to the original context
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, Sub(10)), Mul(2), data)
fmt.Println(preComposedResult)
Output:

[{a 1} {b 12} {c 23} {d 34} {e 45}]
[{a 2} {b 24} {c 46} {d 68} {e 90}]
[{a 12} {b 34} {c 56} {d 78} {e 100}]

func SubCol

func SubCol[I, A any](start int, length int) Optic[Void, Collection[I, A, Pure], Collection[I, A, Pure], Collection[I, A, Pure], Collection[I, A, Pure], ReturnOne, ReadWrite, UniDir, Pure]

SubCol returns a collection operation that removes elements from the start and end of a Collection].

length may be negative in which case it will remove length elements from the end of the Collection

See: - [SubColP] for a non polymorphic version - FilteredCol for a version that can remove arbitrary elements

Example
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var result []int = MustModify(
	SliceToCol[int](),
	SubCol[int, int](2, 2),
	data,
)

fmt.Println(result)

var negativeLengthResult []int = MustModify(
	SliceToCol[int](),
	SubCol[int, int](2, -2),
	data,
)

fmt.Println(negativeLengthResult)
Output:

[3 4]
[3 4 5 6 7 8]

func SubFrom

func SubFrom[A Arithmetic](left A) Optic[Void, A, A, A, A, ReturnOne, ReadWrite, BiDir, Pure]

SubFrom returns a Iso that performs a subtraction from a constant value.

See:

  • Sub for a version that subtracts a constant value.
  • SubOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []lo.Tuple2[string, int]{
	lo.T2("a", 11),
	lo.T2("b", 22),
	lo.T2("c", 33),
	lo.T2("d", 44),
	lo.T2("e", 55),
}

//Focus the second element in a slice of tuples
optic := Compose(TraverseSlice[lo.Tuple2[string, int]](), T2B[string, int]())

//Subtract each focused value from 100.
var modifyResult []lo.Tuple2[string, int] = MustModify(optic, SubFrom(100), data)
fmt.Println(modifyResult)

//Getters are optics and can be composed.
//This composition subtracts from 100 then multiplies by 2
var composedResult []lo.Tuple2[string, int] = MustModify(optic, Compose(SubFrom(100), Mul(2)), data)
fmt.Println(composedResult)

//The getter can be composed with the query optic.
//This has the effect of applying the Mul operation in a subtract from 100 context
//But when the result is built the value is added o again to return it to the original context
var preComposedResult []lo.Tuple2[string, int] = MustModify(Compose(optic, SubFrom(10)), Mul(2), data)
fmt.Println(preComposedResult)
Output:

[{a 89} {b 78} {c 67} {d 56} {e 45}]
[{a 178} {b 156} {c 134} {d 112} {e 90}]
[{a 12} {b 34} {c 56} {d 78} {e 100}]

func SubOp

func SubOp[S any, A Arithmetic, LRET, RRET TReturnOne, LERR, RERR any](left Operation[S, A, LRET, LERR], right Operation[S, A, RRET, RERR]) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[LERR, RERR]]

SubOp returns an Operation expression that subtracts the focuses of 2 [Operation]s.

See:

  • Add for the constant version.
Example
data := []lo.Tuple2[int, int]{
	lo.T2(6, 1),
	lo.T2(7, 2),
	lo.T2(8, 3),
	lo.T2(9, 4),
	lo.T2(10, 5),
}

//2 optics to focus on the first and second elements of the tuple
leftOptic := T2A[int, int]()
rightOptic := T2B[int, int]()

//Create a getter that applies the Sub function to the focuses of both optics
subber := SubOp(leftOptic, rightOptic)

var singleValueResult int = MustGet(subber, lo.T2(10, 2))
fmt.Println(singleValueResult) // 8

//The created function is suitable for usage together with polymorphic optics that have a source focus of lo.Tuple2[int, int] but result focus type of int
var overResult []int = MustModify(TraverseSliceP[lo.Tuple2[int, int], int](), subber, data)
fmt.Println(overResult) // [5 5 5 5 5]
Output:

8
[5 5 5 5 5]

func SubSlice

func SubSlice[A any](start int, length int) Optic[Void, []A, []A, []A, []A, ReturnOne, ReadWrite, UniDir, Pure]

SubSlice applies the SubCol operation to a Slice

Example
data := lo.T2(
	1,
	[]string{
		"alpha",
		"beta",
		"gamma",
		"delta",
	},
)

var getRes []string = MustGet(
	Compose(
		T2B[int, []string](),
		SubSlice[string](1, -1),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, []string] = MustModify(
	T2B[int, []string](),
	SubSlice[string](1, -1),
	data,
)
fmt.Println(modifyRes)
Output:

[beta gamma]
{1 [beta gamma]}

func SubString

func SubString(start int, length int) Optic[Void, string, string, string, string, ReturnOne, ReadWrite, UniDir, Pure]

SubString applies the SubCol operation to a String

Example
data := lo.T2(1, "Lorem ipsum dolor sit amet")

var getRes string = MustGet(
	Compose(
		T2B[int, string](),
		SubString(1, -1),
	),
	data,
)
fmt.Println(getRes)

var modifyRes lo.Tuple2[int, string] = MustModify(
	T2B[int, string](),
	SubString(1, -1),
	data,
)
fmt.Println(modifyRes)
Output:

orem ipsum dolor sit ame
{1 orem ipsum dolor sit ame}

func SubT2

func SubT2[A Arithmetic]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnOne, ReadOnly, UniDir, Pure]

SubT2 returns an BinaryOp that subtracts 2 values.

See:

  • Sub for a unary version.
  • SubOp for a version that is applied to the focus of 2 [Operation]s.
Example
data := []int{5, 2, 10, 3}

//returns a reducer that subtracts all the numbers in a slice from 100
optic := Reduce(
	TraverseSlice[int](),
	AsReducer(100, SubT2[int]()),
)

var res int
res, ok := MustGetFirst(
	optic,
	data,
)
fmt.Println(res, ok)
Output:

80 true

func SwappedT2

func SwappedT2[A, B any]() Optic[Void, lo.Tuple2[A, B], lo.Tuple2[A, B], lo.Tuple2[B, A], lo.Tuple2[B, A], ReturnOne, ReadWrite, BiDir, Pure]

SwappedT2 returns an Iso that focuses on the swapped values of a lo.Tuple2

Example
t2 := lo.T2("one", 1)

var viewResult lo.Tuple2[int, string] = MustGet(SwappedT2[string, int](), t2)
fmt.Println(viewResult)

//Note we set a swapped value and the lens converts it back to the original order
var setResult lo.Tuple2[string, int] = MustSet(SwappedT2[string, int](), lo.T2(2, "two"), t2)
fmt.Println(setResult)
Output:

{1 one}
{two 2}

func Switch

func Switch[I, S, T, A, B, RET1, RETD, RW1, RWD, DIR1, DIRD, ERRP1, ERR1, ERRD any](
	case1 switchCase[I, S, T, A, B, RET1, RW1, DIR1, ERR1, ERRP1],
	def Optic[I, S, T, A, B, RETD, RWD, DIRD, ERRD],
) Optic[I, S, T, A, B, CompositionTree[RET1, RETD], CompositionTree[RW1, RWD], UniDir, CompositionTree[CompositionTree[ERR1, ERRP1], ERRD]]

func Switch2

func Switch2[I, S, T, A, B, RET1, RW1, DIR1, ERRP1, ERR1, RET2, RW2, DIR2, ERRP2, ERR2, RETD, RWD, DIRD, ERRD any](
	case1 switchCase[I, S, T, A, B, RET1, RW1, DIR1, ERR1, ERRP1],
	case2 switchCase[I, S, T, A, B, RET2, RW2, DIR2, ERR2, ERRP2],
	def Optic[I, S, T, A, B, RETD, RWD, DIRD, ERRD],
) Optic[I, S, T, A, B, CompositionTree[CompositionTree[RET1, RET2], RETD], CompositionTree[CompositionTree[RW1, RW2], RWD], UniDir, CompositionTree[CompositionTree[CompositionTree[ERR1, ERRP1], CompositionTree[ERR2, ERRP2]], ERRD]]

func Switch3

func Switch3[I, S, T, A, B, RET1, RW1, DIR1, ERRP1, ERR1, RET2, RW2, DIR2, ERRP2, ERR2, RET3, RW3, DIR3, ERRP3, ERR3, RETD, RWD, DIRD, ERRD any](
	case1 switchCase[I, S, T, A, B, RET1, RW1, DIR1, ERR1, ERRP1],
	case2 switchCase[I, S, T, A, B, RET2, RW2, DIR2, ERR2, ERRP2],
	case3 switchCase[I, S, T, A, B, RET3, RW3, DIR3, ERR3, ERRP3],
	def Optic[I, S, T, A, B, RETD, RWD, DIRD, ERRD],
) Optic[I, S, T, A, B, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], RETD], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], RWD], UniDir, CompositionTree[CompositionTree[CompositionTree[CompositionTree[ERR1, ERRP1], CompositionTree[ERR2, ERRP2]], CompositionTree[ERR3, ERRP3]], ERRD]]

func Switch4

func Switch4[I, S, T, A, B, RET1, RW1, DIR1, ERRP1, ERR1, RET2, RW2, DIR2, ERRP2, ERR2, RET3, RW3, DIR3, ERRP3, ERR3, RET4, RW4, DIR4, ERRP4, ERR4, RETD, RWD, DIRD, ERRD any](
	case1 switchCase[I, S, T, A, B, RET1, RW1, DIR1, ERR1, ERRP1],
	case2 switchCase[I, S, T, A, B, RET2, RW2, DIR2, ERR2, ERRP2],
	case3 switchCase[I, S, T, A, B, RET3, RW3, DIR3, ERR3, ERRP3],
	case4 switchCase[I, S, T, A, B, RET4, RW4, DIR4, ERR4, ERRP4],
	def Optic[I, S, T, A, B, RETD, RWD, DIRD, ERRD],
) Optic[I, S, T, A, B, CompositionTree[CompositionTree[CompositionTree[RET1, RET2], RET3], RETD], CompositionTree[CompositionTree[CompositionTree[RW1, RW2], RW3], RWD], UniDir, CompositionTree[CompositionTree[CompositionTree[CompositionTree[ERR1, ERRP1], CompositionTree[ERR2, ERRP2]], CompositionTree[CompositionTree[ERR3, ERRP3], CompositionTree[ERR4, ERRP4]]], ERRD]]

func SwitchN

func SwitchN[I, S, T, A, B, RET, RW, DIR, ERR, ERRP any](def Optic[I, S, T, A, B, RET, RW, DIR, ERR], cases ...switchCase[I, S, T, A, B, RET, RW, DIR, ERR, ERRP]) Optic[I, S, T, A, B, RET, RW, UniDir, CompositionTree[ERR, ERRP]]

func T2A

func T2A[A any, B any]() Optic[int, lo.Tuple2[A, B], lo.Tuple2[A, B], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T2A returns a Lens focusing on element 0 of a lo.Tuple2

See: T2AP for a polymorphic version

Example
t2 := lo.T2("one", 1)

var viewResult string = MustGet(T2A[string, int](), t2)
fmt.Println(viewResult)

var setResult lo.Tuple2[string, int] = MustSet(T2A[string, int](), "two", t2)
fmt.Println(setResult)
Output:

one
{two 1}

func T2AP

func T2AP[A any, B any, A2 any]() Optic[int, lo.Tuple2[A, B], lo.Tuple2[A2, B], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T2AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple2

See: T2A for a non polymorphic version

Example
t2 := lo.T2("one", 1)

var viewResult string = MustGet(T2AP[string, int, int](), t2)
fmt.Println(viewResult)

var setResult lo.Tuple2[int, int] = MustSet(T2AP[string, int, int](), 2, t2)
fmt.Println(setResult)
Output:

one
{2 1}

func T2B

func T2B[A any, B any]() Optic[int, lo.Tuple2[A, B], lo.Tuple2[A, B], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T2B returns a Lens focusing on element 1 of a lo.Tuple2

See: T2BP for a polymorphic version

Example
t2 := lo.T2("one", 1)

var viewResult int = MustGet(T2B[string, int](), t2)
fmt.Println(viewResult)

var setResult lo.Tuple2[string, int] = MustSet(T2B[string, int](), 2, t2)
fmt.Println(setResult)
Output:

1
{one 2}

func T2BP

func T2BP[A any, B any, B2 any]() Optic[int, lo.Tuple2[A, B], lo.Tuple2[A, B2], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T2BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple2

See: T2B for a non polymorphic version

Example
t2 := lo.T2("one", 1)

var viewResult int = MustGet(T2BP[string, int, string](), t2)
fmt.Println(viewResult)

var setResult lo.Tuple2[string, string] = MustSet(T2BP[string, int, string](), "two", t2)
fmt.Println(setResult)
Output:

1
{one two}

func T2Of

func T2Of[I0 any, I1 any, S, T any, A0 any, A1 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, T, A1, A1, RET1, RW1, DIR1, ERR1]) Optic[lo.Tuple2[I0, I1], S, T, lo.Tuple2[A0, A1], lo.Tuple2[A0, A1], CompositionTree[RET0, RET1], CompositionTree[RW0, RW1], UniDir, CompositionTree[ERR0, ERR1]]

The T2Of Combinator constructs a lo.Tuple2 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

Example
type Person struct {
	Name string
	Age  int
}

personName := FieldLens(func(p *Person) *string { return &p.Name })
personAge := FieldLens(func(p *Person) *int { return &p.Age })

optic := T2Of(personName, personAge)

var res lo.Tuple2[string, int] = MustGet(optic, Person{Name: "Max Mustermann", Age: 46})
fmt.Println(res)

var modifyRes Person = MustModify(Compose(optic, T2B[string, int]()), Add(1), Person{Name: "Max Mustermann", Age: 46})
fmt.Println("Name:", modifyRes.Name)
fmt.Println("Age:", modifyRes.Age)
Output:

{Max Mustermann 46}
Name: Max Mustermann
Age: 47

func T2ToCol

func T2ToCol[A any]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T2ToCol returns an Iso that converts a lo.Tuple2 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T2PCol for a polymorphic version

func T2ToColP

func T2ToColP[A any, B any]() Optic[Void, lo.Tuple2[A, A], lo.Tuple2[B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T2CToolP returns a polymorphic Iso that converts a lo.Tuple2 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T2ToCol for a non polymorphic version

func T3A

func T3A[A any, B any, C any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A, B, C], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T3A returns a Lens focusing on element 0 of a lo.Tuple3

See: T3AP for a polymorphic version

func T3AP

func T3AP[A any, B any, C any, A2 any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A2, B, C], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T3AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple3

See: T3A for a non polymorphic version

func T3B

func T3B[A any, B any, C any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A, B, C], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T3B returns a Lens focusing on element 1 of a lo.Tuple3

See: T3BP for a polymorphic version

func T3BP

func T3BP[A any, B any, C any, B2 any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A, B2, C], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T3BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple3

See: T3B for a non polymorphic version

func T3C

func T3C[A any, B any, C any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A, B, C], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T3C returns a Lens focusing on element 2 of a lo.Tuple3

See: T3CP for a polymorphic version

func T3CP

func T3CP[A any, B any, C any, C2 any]() Optic[int, lo.Tuple3[A, B, C], lo.Tuple3[A, B, C2], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T3CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple3

See: T3C for a non polymorphic version

func T3Of

func T3Of[I0 any, I1 any, I2 any, S any, A0 any, A1 any, A2 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2]) Optic[lo.Tuple3[I0, I1, I2], S, S, lo.Tuple3[A0, A1, A2], lo.Tuple3[A0, A1, A2], CompositionTree[CompositionTree[RET0, RET1], RET2], CompositionTree[CompositionTree[RW0, RW1], RW2], UniDir, CompositionTree[CompositionTree[ERR0, ERR1], ERR2]]

The T3Of Combinator constructs a lo.Tuple3 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T3ToCol

func T3ToCol[A any]() Optic[Void, lo.Tuple3[A, A, A], lo.Tuple3[A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T3ToCol returns an Iso that converts a lo.Tuple3 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T3PCol for a polymorphic version

func T3ToColP

func T3ToColP[A any, B any]() Optic[Void, lo.Tuple3[A, A, A], lo.Tuple3[B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T3CToolP returns a polymorphic Iso that converts a lo.Tuple3 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T3ToCol for a non polymorphic version

func T4A

func T4A[A any, B any, C any, D any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C, D], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T4A returns a Lens focusing on element 0 of a lo.Tuple4

See: T4AP for a polymorphic version

func T4AP

func T4AP[A any, B any, C any, D any, A2 any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A2, B, C, D], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T4AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple4

See: T4A for a non polymorphic version

func T4B

func T4B[A any, B any, C any, D any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C, D], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T4B returns a Lens focusing on element 1 of a lo.Tuple4

See: T4BP for a polymorphic version

func T4BP

func T4BP[A any, B any, C any, D any, B2 any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B2, C, D], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T4BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple4

See: T4B for a non polymorphic version

func T4C

func T4C[A any, B any, C any, D any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C, D], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T4C returns a Lens focusing on element 2 of a lo.Tuple4

See: T4CP for a polymorphic version

func T4CP

func T4CP[A any, B any, C any, D any, C2 any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C2, D], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T4CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple4

See: T4C for a non polymorphic version

func T4D

func T4D[A any, B any, C any, D any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C, D], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T4D returns a Lens focusing on element 3 of a lo.Tuple4

See: T4DP for a polymorphic version

func T4DP

func T4DP[A any, B any, C any, D any, D2 any]() Optic[int, lo.Tuple4[A, B, C, D], lo.Tuple4[A, B, C, D2], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T4DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple4

See: T4D for a non polymorphic version

func T4Of

func T4Of[I0 any, I1 any, I2 any, I3 any, S any, A0 any, A1 any, A2 any, A3 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3]) Optic[lo.Tuple4[I0, I1, I2, I3], S, S, lo.Tuple4[A0, A1, A2, A3], lo.Tuple4[A0, A1, A2, A3], CompositionTree[CompositionTree[RET0, RET1], CompositionTree[RET2, RET3]], CompositionTree[CompositionTree[RW0, RW1], CompositionTree[RW2, RW3]], UniDir, CompositionTree[CompositionTree[ERR0, ERR1], CompositionTree[ERR2, ERR3]]]

The T4Of Combinator constructs a lo.Tuple4 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T4ToCol

func T4ToCol[A any]() Optic[Void, lo.Tuple4[A, A, A, A], lo.Tuple4[A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T4ToCol returns an Iso that converts a lo.Tuple4 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T4PCol for a polymorphic version

func T4ToColP

func T4ToColP[A any, B any]() Optic[Void, lo.Tuple4[A, A, A, A], lo.Tuple4[B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T4CToolP returns a polymorphic Iso that converts a lo.Tuple4 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T4ToCol for a non polymorphic version

func T5A

func T5A[A any, B any, C any, D any, E any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T5A returns a Lens focusing on element 0 of a lo.Tuple5

See: T5AP for a polymorphic version

func T5AP

func T5AP[A any, B any, C any, D any, E any, A2 any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A2, B, C, D, E], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T5AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple5

See: T5A for a non polymorphic version

func T5B

func T5B[A any, B any, C any, D any, E any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T5B returns a Lens focusing on element 1 of a lo.Tuple5

See: T5BP for a polymorphic version

func T5BP

func T5BP[A any, B any, C any, D any, E any, B2 any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B2, C, D, E], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T5BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple5

See: T5B for a non polymorphic version

func T5C

func T5C[A any, B any, C any, D any, E any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T5C returns a Lens focusing on element 2 of a lo.Tuple5

See: T5CP for a polymorphic version

func T5CP

func T5CP[A any, B any, C any, D any, E any, C2 any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C2, D, E], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T5CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple5

See: T5C for a non polymorphic version

func T5D

func T5D[A any, B any, C any, D any, E any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T5D returns a Lens focusing on element 3 of a lo.Tuple5

See: T5DP for a polymorphic version

func T5DP

func T5DP[A any, B any, C any, D any, E any, D2 any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D2, E], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T5DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple5

See: T5D for a non polymorphic version

func T5E

func T5E[A any, B any, C any, D any, E any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E], E, E, ReturnOne, ReadWrite, UniDir, Pure]

T5E returns a Lens focusing on element 4 of a lo.Tuple5

See: T5EP for a polymorphic version

func T5EP

func T5EP[A any, B any, C any, D any, E any, E2 any]() Optic[int, lo.Tuple5[A, B, C, D, E], lo.Tuple5[A, B, C, D, E2], E, E2, ReturnOne, ReadWrite, UniDir, Pure]

T5EP returns a polymorphic Lens focusing on element 4 of a lo.Tuple5

See: T5E for a non polymorphic version

func T5Of

func T5Of[I0 any, I1 any, I2 any, I3 any, I4 any, S any, A0 any, A1 any, A2 any, A3 any, A4 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3], o4 Optic[I4, S, S, A4, A4, RET4, RW4, DIR4, ERR4]) Optic[lo.Tuple5[I0, I1, I2, I3, I4], S, S, lo.Tuple5[A0, A1, A2, A3, A4], lo.Tuple5[A0, A1, A2, A3, A4], CompositionTree[CompositionTree[CompositionTree[RET0, RET1], RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[CompositionTree[RW0, RW1], RW2], CompositionTree[RW3, RW4]], UniDir, CompositionTree[CompositionTree[CompositionTree[ERR0, ERR1], ERR2], CompositionTree[ERR3, ERR4]]]

The T5Of Combinator constructs a lo.Tuple5 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T5ToCol

func T5ToCol[A any]() Optic[Void, lo.Tuple5[A, A, A, A, A], lo.Tuple5[A, A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T5ToCol returns an Iso that converts a lo.Tuple5 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T5PCol for a polymorphic version

func T5ToColP

func T5ToColP[A any, B any]() Optic[Void, lo.Tuple5[A, A, A, A, A], lo.Tuple5[B, B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T5CToolP returns a polymorphic Iso that converts a lo.Tuple5 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T5ToCol for a non polymorphic version

func T6A

func T6A[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T6A returns a Lens focusing on element 0 of a lo.Tuple6

See: T6AP for a polymorphic version

func T6AP

func T6AP[A any, B any, C any, D any, E any, F any, A2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A2, B, C, D, E, F], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T6AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple6

See: T6A for a non polymorphic version

func T6B

func T6B[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T6B returns a Lens focusing on element 1 of a lo.Tuple6

See: T6BP for a polymorphic version

func T6BP

func T6BP[A any, B any, C any, D any, E any, F any, B2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B2, C, D, E, F], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T6BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple6

See: T6B for a non polymorphic version

func T6C

func T6C[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T6C returns a Lens focusing on element 2 of a lo.Tuple6

See: T6CP for a polymorphic version

func T6CP

func T6CP[A any, B any, C any, D any, E any, F any, C2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C2, D, E, F], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T6CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple6

See: T6C for a non polymorphic version

func T6D

func T6D[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T6D returns a Lens focusing on element 3 of a lo.Tuple6

See: T6DP for a polymorphic version

func T6DP

func T6DP[A any, B any, C any, D any, E any, F any, D2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D2, E, F], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T6DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple6

See: T6D for a non polymorphic version

func T6E

func T6E[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], E, E, ReturnOne, ReadWrite, UniDir, Pure]

T6E returns a Lens focusing on element 4 of a lo.Tuple6

See: T6EP for a polymorphic version

func T6EP

func T6EP[A any, B any, C any, D any, E any, F any, E2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E2, F], E, E2, ReturnOne, ReadWrite, UniDir, Pure]

T6EP returns a polymorphic Lens focusing on element 4 of a lo.Tuple6

See: T6E for a non polymorphic version

func T6F

func T6F[A any, B any, C any, D any, E any, F any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F], F, F, ReturnOne, ReadWrite, UniDir, Pure]

T6F returns a Lens focusing on element 5 of a lo.Tuple6

See: T6FP for a polymorphic version

func T6FP

func T6FP[A any, B any, C any, D any, E any, F any, F2 any]() Optic[int, lo.Tuple6[A, B, C, D, E, F], lo.Tuple6[A, B, C, D, E, F2], F, F2, ReturnOne, ReadWrite, UniDir, Pure]

T6FP returns a polymorphic Lens focusing on element 5 of a lo.Tuple6

See: T6F for a non polymorphic version

func T6Of

func T6Of[I0 any, I1 any, I2 any, I3 any, I4 any, I5 any, S any, A0 any, A1 any, A2 any, A3 any, A4 any, A5 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3], o4 Optic[I4, S, S, A4, A4, RET4, RW4, DIR4, ERR4], o5 Optic[I5, S, S, A5, A5, RET5, RW5, DIR5, ERR5]) Optic[lo.Tuple6[I0, I1, I2, I3, I4, I5], S, S, lo.Tuple6[A0, A1, A2, A3, A4, A5], lo.Tuple6[A0, A1, A2, A3, A4, A5], CompositionTree[CompositionTree[CompositionTree[RET0, RET1], RET2], CompositionTree[CompositionTree[RET3, RET4], RET5]], CompositionTree[CompositionTree[CompositionTree[RW0, RW1], RW2], CompositionTree[CompositionTree[RW3, RW4], RW5]], UniDir, CompositionTree[CompositionTree[CompositionTree[ERR0, ERR1], ERR2], CompositionTree[CompositionTree[ERR3, ERR4], ERR5]]]

The T6Of Combinator constructs a lo.Tuple6 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T6ToCol

func T6ToCol[A any]() Optic[Void, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[A, A, A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T6ToCol returns an Iso that converts a lo.Tuple6 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T6PCol for a polymorphic version

func T6ToColP

func T6ToColP[A any, B any]() Optic[Void, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[B, B, B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T6CToolP returns a polymorphic Iso that converts a lo.Tuple6 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T6ToCol for a non polymorphic version

func T7A

func T7A[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T7A returns a Lens focusing on element 0 of a lo.Tuple7

See: T7AP for a polymorphic version

func T7AP

func T7AP[A any, B any, C any, D any, E any, F any, G any, A2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A2, B, C, D, E, F, G], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T7AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple7

See: T7A for a non polymorphic version

func T7B

func T7B[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T7B returns a Lens focusing on element 1 of a lo.Tuple7

See: T7BP for a polymorphic version

func T7BP

func T7BP[A any, B any, C any, D any, E any, F any, G any, B2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B2, C, D, E, F, G], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T7BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple7

See: T7B for a non polymorphic version

func T7C

func T7C[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T7C returns a Lens focusing on element 2 of a lo.Tuple7

See: T7CP for a polymorphic version

func T7CP

func T7CP[A any, B any, C any, D any, E any, F any, G any, C2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C2, D, E, F, G], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T7CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple7

See: T7C for a non polymorphic version

func T7D

func T7D[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T7D returns a Lens focusing on element 3 of a lo.Tuple7

See: T7DP for a polymorphic version

func T7DP

func T7DP[A any, B any, C any, D any, E any, F any, G any, D2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D2, E, F, G], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T7DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple7

See: T7D for a non polymorphic version

func T7E

func T7E[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], E, E, ReturnOne, ReadWrite, UniDir, Pure]

T7E returns a Lens focusing on element 4 of a lo.Tuple7

See: T7EP for a polymorphic version

func T7EP

func T7EP[A any, B any, C any, D any, E any, F any, G any, E2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E2, F, G], E, E2, ReturnOne, ReadWrite, UniDir, Pure]

T7EP returns a polymorphic Lens focusing on element 4 of a lo.Tuple7

See: T7E for a non polymorphic version

func T7F

func T7F[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], F, F, ReturnOne, ReadWrite, UniDir, Pure]

T7F returns a Lens focusing on element 5 of a lo.Tuple7

See: T7FP for a polymorphic version

func T7FP

func T7FP[A any, B any, C any, D any, E any, F any, G any, F2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F2, G], F, F2, ReturnOne, ReadWrite, UniDir, Pure]

T7FP returns a polymorphic Lens focusing on element 5 of a lo.Tuple7

See: T7F for a non polymorphic version

func T7G

func T7G[A any, B any, C any, D any, E any, F any, G any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G], G, G, ReturnOne, ReadWrite, UniDir, Pure]

T7G returns a Lens focusing on element 6 of a lo.Tuple7

See: T7GP for a polymorphic version

func T7GP

func T7GP[A any, B any, C any, D any, E any, F any, G any, G2 any]() Optic[int, lo.Tuple7[A, B, C, D, E, F, G], lo.Tuple7[A, B, C, D, E, F, G2], G, G2, ReturnOne, ReadWrite, UniDir, Pure]

T7GP returns a polymorphic Lens focusing on element 6 of a lo.Tuple7

See: T7G for a non polymorphic version

func T7Of

func T7Of[I0 any, I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, S any, A0 any, A1 any, A2 any, A3 any, A4 any, A5 any, A6 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3], o4 Optic[I4, S, S, A4, A4, RET4, RW4, DIR4, ERR4], o5 Optic[I5, S, S, A5, A5, RET5, RW5, DIR5, ERR5], o6 Optic[I6, S, S, A6, A6, RET6, RW6, DIR6, ERR6]) Optic[lo.Tuple7[I0, I1, I2, I3, I4, I5, I6], S, S, lo.Tuple7[A0, A1, A2, A3, A4, A5, A6], lo.Tuple7[A0, A1, A2, A3, A4, A5, A6], CompositionTree[CompositionTree[CompositionTree[RET0, RET1], CompositionTree[RET2, RET3]], CompositionTree[CompositionTree[RET4, RET5], RET6]], CompositionTree[CompositionTree[CompositionTree[RW0, RW1], CompositionTree[RW2, RW3]], CompositionTree[CompositionTree[RW4, RW5], RW6]], UniDir, CompositionTree[CompositionTree[CompositionTree[ERR0, ERR1], CompositionTree[ERR2, ERR3]], CompositionTree[CompositionTree[ERR4, ERR5], ERR6]]]

The T7Of Combinator constructs a lo.Tuple7 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T7ToCol

func T7ToCol[A any]() Optic[Void, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[A, A, A, A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T7ToCol returns an Iso that converts a lo.Tuple7 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T7PCol for a polymorphic version

func T7ToColP

func T7ToColP[A any, B any]() Optic[Void, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[B, B, B, B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T7CToolP returns a polymorphic Iso that converts a lo.Tuple7 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T7ToCol for a non polymorphic version

func T8A

func T8A[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T8A returns a Lens focusing on element 0 of a lo.Tuple8

See: T8AP for a polymorphic version

func T8AP

func T8AP[A any, B any, C any, D any, E any, F any, G any, H any, A2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A2, B, C, D, E, F, G, H], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T8AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple8

See: T8A for a non polymorphic version

func T8B

func T8B[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T8B returns a Lens focusing on element 1 of a lo.Tuple8

See: T8BP for a polymorphic version

func T8BP

func T8BP[A any, B any, C any, D any, E any, F any, G any, H any, B2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B2, C, D, E, F, G, H], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T8BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple8

See: T8B for a non polymorphic version

func T8C

func T8C[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T8C returns a Lens focusing on element 2 of a lo.Tuple8

See: T8CP for a polymorphic version

func T8CP

func T8CP[A any, B any, C any, D any, E any, F any, G any, H any, C2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C2, D, E, F, G, H], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T8CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple8

See: T8C for a non polymorphic version

func T8D

func T8D[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T8D returns a Lens focusing on element 3 of a lo.Tuple8

See: T8DP for a polymorphic version

func T8DP

func T8DP[A any, B any, C any, D any, E any, F any, G any, H any, D2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D2, E, F, G, H], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T8DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple8

See: T8D for a non polymorphic version

func T8E

func T8E[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], E, E, ReturnOne, ReadWrite, UniDir, Pure]

T8E returns a Lens focusing on element 4 of a lo.Tuple8

See: T8EP for a polymorphic version

func T8EP

func T8EP[A any, B any, C any, D any, E any, F any, G any, H any, E2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E2, F, G, H], E, E2, ReturnOne, ReadWrite, UniDir, Pure]

T8EP returns a polymorphic Lens focusing on element 4 of a lo.Tuple8

See: T8E for a non polymorphic version

func T8F

func T8F[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], F, F, ReturnOne, ReadWrite, UniDir, Pure]

T8F returns a Lens focusing on element 5 of a lo.Tuple8

See: T8FP for a polymorphic version

func T8FP

func T8FP[A any, B any, C any, D any, E any, F any, G any, H any, F2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F2, G, H], F, F2, ReturnOne, ReadWrite, UniDir, Pure]

T8FP returns a polymorphic Lens focusing on element 5 of a lo.Tuple8

See: T8F for a non polymorphic version

func T8G

func T8G[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], G, G, ReturnOne, ReadWrite, UniDir, Pure]

T8G returns a Lens focusing on element 6 of a lo.Tuple8

See: T8GP for a polymorphic version

func T8GP

func T8GP[A any, B any, C any, D any, E any, F any, G any, H any, G2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G2, H], G, G2, ReturnOne, ReadWrite, UniDir, Pure]

T8GP returns a polymorphic Lens focusing on element 6 of a lo.Tuple8

See: T8G for a non polymorphic version

func T8H

func T8H[A any, B any, C any, D any, E any, F any, G any, H any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H], H, H, ReturnOne, ReadWrite, UniDir, Pure]

T8H returns a Lens focusing on element 7 of a lo.Tuple8

See: T8HP for a polymorphic version

func T8HP

func T8HP[A any, B any, C any, D any, E any, F any, G any, H any, H2 any]() Optic[int, lo.Tuple8[A, B, C, D, E, F, G, H], lo.Tuple8[A, B, C, D, E, F, G, H2], H, H2, ReturnOne, ReadWrite, UniDir, Pure]

T8HP returns a polymorphic Lens focusing on element 7 of a lo.Tuple8

See: T8H for a non polymorphic version

func T8Of

func T8Of[I0 any, I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, S any, A0 any, A1 any, A2 any, A3 any, A4 any, A5 any, A6 any, A7 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3], o4 Optic[I4, S, S, A4, A4, RET4, RW4, DIR4, ERR4], o5 Optic[I5, S, S, A5, A5, RET5, RW5, DIR5, ERR5], o6 Optic[I6, S, S, A6, A6, RET6, RW6, DIR6, ERR6], o7 Optic[I7, S, S, A7, A7, RET7, RW7, DIR7, ERR7]) Optic[lo.Tuple8[I0, I1, I2, I3, I4, I5, I6, I7], S, S, lo.Tuple8[A0, A1, A2, A3, A4, A5, A6, A7], lo.Tuple8[A0, A1, A2, A3, A4, A5, A6, A7], CompositionTree[CompositionTree[CompositionTree[RET0, RET1], CompositionTree[RET2, RET3]], CompositionTree[CompositionTree[RET4, RET5], CompositionTree[RET6, RET7]]], CompositionTree[CompositionTree[CompositionTree[RW0, RW1], CompositionTree[RW2, RW3]], CompositionTree[CompositionTree[RW4, RW5], CompositionTree[RW6, RW7]]], UniDir, CompositionTree[CompositionTree[CompositionTree[ERR0, ERR1], CompositionTree[ERR2, ERR3]], CompositionTree[CompositionTree[ERR4, ERR5], CompositionTree[ERR6, ERR7]]]]

The T8Of Combinator constructs a lo.Tuple8 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T8ToCol

func T8ToCol[A any]() Optic[Void, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[A, A, A, A, A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T8ToCol returns an Iso that converts a lo.Tuple8 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T8PCol for a polymorphic version

func T8ToColP

func T8ToColP[A any, B any]() Optic[Void, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[B, B, B, B, B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T8CToolP returns a polymorphic Iso that converts a lo.Tuple8 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T8ToCol for a non polymorphic version

func T9A

func T9A[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], A, A, ReturnOne, ReadWrite, UniDir, Pure]

T9A returns a Lens focusing on element 0 of a lo.Tuple9

See: T9AP for a polymorphic version

func T9AP

func T9AP[A any, B any, C any, D any, E any, F any, G any, H any, I any, A2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A2, B, C, D, E, F, G, H, I], A, A2, ReturnOne, ReadWrite, UniDir, Pure]

T9AP returns a polymorphic Lens focusing on element 0 of a lo.Tuple9

See: T9A for a non polymorphic version

func T9B

func T9B[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], B, B, ReturnOne, ReadWrite, UniDir, Pure]

T9B returns a Lens focusing on element 1 of a lo.Tuple9

See: T9BP for a polymorphic version

func T9BP

func T9BP[A any, B any, C any, D any, E any, F any, G any, H any, I any, B2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B2, C, D, E, F, G, H, I], B, B2, ReturnOne, ReadWrite, UniDir, Pure]

T9BP returns a polymorphic Lens focusing on element 1 of a lo.Tuple9

See: T9B for a non polymorphic version

func T9C

func T9C[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], C, C, ReturnOne, ReadWrite, UniDir, Pure]

T9C returns a Lens focusing on element 2 of a lo.Tuple9

See: T9CP for a polymorphic version

func T9CP

func T9CP[A any, B any, C any, D any, E any, F any, G any, H any, I any, C2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C2, D, E, F, G, H, I], C, C2, ReturnOne, ReadWrite, UniDir, Pure]

T9CP returns a polymorphic Lens focusing on element 2 of a lo.Tuple9

See: T9C for a non polymorphic version

func T9D

func T9D[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], D, D, ReturnOne, ReadWrite, UniDir, Pure]

T9D returns a Lens focusing on element 3 of a lo.Tuple9

See: T9DP for a polymorphic version

func T9DP

func T9DP[A any, B any, C any, D any, E any, F any, G any, H any, I any, D2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D2, E, F, G, H, I], D, D2, ReturnOne, ReadWrite, UniDir, Pure]

T9DP returns a polymorphic Lens focusing on element 3 of a lo.Tuple9

See: T9D for a non polymorphic version

func T9E

func T9E[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], E, E, ReturnOne, ReadWrite, UniDir, Pure]

T9E returns a Lens focusing on element 4 of a lo.Tuple9

See: T9EP for a polymorphic version

func T9EP

func T9EP[A any, B any, C any, D any, E any, F any, G any, H any, I any, E2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E2, F, G, H, I], E, E2, ReturnOne, ReadWrite, UniDir, Pure]

T9EP returns a polymorphic Lens focusing on element 4 of a lo.Tuple9

See: T9E for a non polymorphic version

func T9F

func T9F[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], F, F, ReturnOne, ReadWrite, UniDir, Pure]

T9F returns a Lens focusing on element 5 of a lo.Tuple9

See: T9FP for a polymorphic version

func T9FP

func T9FP[A any, B any, C any, D any, E any, F any, G any, H any, I any, F2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F2, G, H, I], F, F2, ReturnOne, ReadWrite, UniDir, Pure]

T9FP returns a polymorphic Lens focusing on element 5 of a lo.Tuple9

See: T9F for a non polymorphic version

func T9G

func T9G[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], G, G, ReturnOne, ReadWrite, UniDir, Pure]

T9G returns a Lens focusing on element 6 of a lo.Tuple9

See: T9GP for a polymorphic version

func T9GP

func T9GP[A any, B any, C any, D any, E any, F any, G any, H any, I any, G2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G2, H, I], G, G2, ReturnOne, ReadWrite, UniDir, Pure]

T9GP returns a polymorphic Lens focusing on element 6 of a lo.Tuple9

See: T9G for a non polymorphic version

func T9H

func T9H[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], H, H, ReturnOne, ReadWrite, UniDir, Pure]

T9H returns a Lens focusing on element 7 of a lo.Tuple9

See: T9HP for a polymorphic version

func T9HP

func T9HP[A any, B any, C any, D any, E any, F any, G any, H any, I any, H2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H2, I], H, H2, ReturnOne, ReadWrite, UniDir, Pure]

T9HP returns a polymorphic Lens focusing on element 7 of a lo.Tuple9

See: T9H for a non polymorphic version

func T9I

func T9I[A any, B any, C any, D any, E any, F any, G any, H any, I any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I], I, I, ReturnOne, ReadWrite, UniDir, Pure]

T9I returns a Lens focusing on element 8 of a lo.Tuple9

See: T9IP for a polymorphic version

func T9IP

func T9IP[A any, B any, C any, D any, E any, F any, G any, H any, I any, I2 any]() Optic[int, lo.Tuple9[A, B, C, D, E, F, G, H, I], lo.Tuple9[A, B, C, D, E, F, G, H, I2], I, I2, ReturnOne, ReadWrite, UniDir, Pure]

T9IP returns a polymorphic Lens focusing on element 8 of a lo.Tuple9

See: T9I for a non polymorphic version

func T9Of

func T9Of[I0 any, I1 any, I2 any, I3 any, I4 any, I5 any, I6 any, I7 any, I8 any, S any, A0 any, A1 any, A2 any, A3 any, A4 any, A5 any, A6 any, A7 any, A8 any, RET0 any, RW0 any, DIR0 any, ERR0 any, RET1 any, RW1 any, DIR1 any, ERR1 any, RET2 any, RW2 any, DIR2 any, ERR2 any, RET3 any, RW3 any, DIR3 any, ERR3 any, RET4 any, RW4 any, DIR4 any, ERR4 any, RET5 any, RW5 any, DIR5 any, ERR5 any, RET6 any, RW6 any, DIR6 any, ERR6 any, RET7 any, RW7 any, DIR7 any, ERR7 any, RET8 any, RW8 any, DIR8 any, ERR8 any](o0 Optic[I0, S, S, A0, A0, RET0, RW0, DIR0, ERR0], o1 Optic[I1, S, S, A1, A1, RET1, RW1, DIR1, ERR1], o2 Optic[I2, S, S, A2, A2, RET2, RW2, DIR2, ERR2], o3 Optic[I3, S, S, A3, A3, RET3, RW3, DIR3, ERR3], o4 Optic[I4, S, S, A4, A4, RET4, RW4, DIR4, ERR4], o5 Optic[I5, S, S, A5, A5, RET5, RW5, DIR5, ERR5], o6 Optic[I6, S, S, A6, A6, RET6, RW6, DIR6, ERR6], o7 Optic[I7, S, S, A7, A7, RET7, RW7, DIR7, ERR7], o8 Optic[I8, S, S, A8, A8, RET8, RW8, DIR8, ERR8]) Optic[lo.Tuple9[I0, I1, I2, I3, I4, I5, I6, I7, I8], S, S, lo.Tuple9[A0, A1, A2, A3, A4, A5, A6, A7, A8], lo.Tuple9[A0, A1, A2, A3, A4, A5, A6, A7, A8], CompositionTree[CompositionTree[CompositionTree[CompositionTree[RET0, RET1], RET2], CompositionTree[RET3, RET4]], CompositionTree[CompositionTree[RET5, RET6], CompositionTree[RET7, RET8]]], CompositionTree[CompositionTree[CompositionTree[CompositionTree[RW0, RW1], RW2], CompositionTree[RW3, RW4]], CompositionTree[CompositionTree[RW5, RW6], CompositionTree[RW7, RW8]]], UniDir, CompositionTree[CompositionTree[CompositionTree[CompositionTree[ERR0, ERR1], ERR2], CompositionTree[ERR3, ERR4]], CompositionTree[CompositionTree[ERR5, ERR6], CompositionTree[ERR7, ERR8]]]]

The T9Of Combinator constructs a lo.Tuple9 whose elements are the focuses of the given [Optic]s

Note: The number of focused tuples is limited by the optic that focuses the least elements.

func T9ToCol

func T9ToCol[A any]() Optic[Void, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[A, A, A, A, A, A, A, A, A], Collection[int, A, Pure], Collection[int, A, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T9ToCol returns an Iso that converts a lo.Tuple9 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T9PCol for a polymorphic version

func T9ToColP

func T9ToColP[A any, B any]() Optic[Void, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[B, B, B, B, B, B, B, B, B], Collection[int, A, Pure], Collection[int, B, Pure], ReturnOne, ReadWrite, BiDir, Pure]

T9CToolP returns a polymorphic Iso that converts a lo.Tuple9 to a Collection

Note: under modification if the collection contains more elements than the tuple then the additional elements are discarded. If the collection contains less elements than the tuple then the tuple elements will default uninitialized values.

See: T9ToCol for a non polymorphic version

func Taking

func Taking[I, S, T, A, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], amount int) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, ERR]

The Taking combinator returns an optic that focuses on the first amount elements in the given optic.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

takingOptic := Taking(TraverseSlice[string](), 2)

listResult := MustGet(SliceOf(takingOptic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(takingOptic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[alpha beta]
[ALPHA BETA gamma delta]

func TakingWhile

func TakingWhile[I, S, T, A, RETI, RW any, DIR, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The TakingWhile combinator focuses on the elements of the given optic until the predicate returns false.

See TakingWhileI for an indexed version.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

//focuses on the elements of the slice until the gamma string is found
optic := TakingWhile(TraverseSlice[string](), Ne("gamma"))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[alpha beta]
[ALPHA BETA gamma delta]

func TakingWhileI

func TakingWhileI[I, S, T, A, RETI, RW any, DIR, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred PredicateI[I, A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The TakingWhileI combinator focuses on the elements of the given optic until the indexed predicate returns false.

See TakingWhile for a non indexed version.

Example
data := map[int]string{
	1: "alpha",
	2: "beta",
	3: "gamma",
	4: "delta",
}

//Focus on elements until the index 3 is found.
optic := TakingWhileI(

	TraverseMap[int, string](), OpI(func(index int, focus string) bool {
		return index < 3
	}))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(listResult)

overResult := MustModify(optic, Op(strings.ToUpper), data)
fmt.Println(overResult)
Output:

[alpha beta]
map[1:ALPHA 2:BETA 3:gamma 4:delta]

func Throw

func Throw[A any]() Optic[Void, error, error, A, A, ReturnOne, ReadWrite, UniDir, Err]

Throw returns a Lens that returns the source error.

Example
optic := Catch(
	ParseInt[int32](10, 32),
	If(
		ErrorIs(strconv.ErrSyntax),
		EErr(Const[error](int32(-1))),
		Ro(Throw[int32]()),
	),
)

viewResult, ok, err := GetFirst(optic, "1")
fmt.Println(viewResult, ok, err)

viewResult, ok, err = GetFirst(optic, "one")
fmt.Println(viewResult, ok, err)

viewResult, ok, err = GetFirst(optic, "2147483648")
fmt.Println(viewResult, ok, err)
Output:

1 true <nil>
-1 true <nil>
0 false strconv.ParseInt: parsing "2147483648": value out of range
optic error path:
	ParseInt(10,32)
	Throw()
	Switch(Case(ErrorIs(invalid syntax) -> Const(-1))Default(Throw()))
	Catch(ParseInt(10,32),Switch(Case(ErrorIs(invalid syntax) -> Const(-1))Default(Throw())),Throw())

func Traversal

func Traversal[S, A any](
	iter func(source S) iter.Seq[A],
	lengthGetter func(source S) int,
	modify func(fmap func(focus A) A, source S) S,
	exprDef ExpressionDef,
) Optic[int, S, S, A, A, ReturnMany, ReadWrite, UniDir, Pure]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

A traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This traversal iterates of the elements of an []int
traverseSlice := Traversal[[]int, int](
	//iter
	func(source []int) iter.Seq[int] {
		return func(yield func(focus int) bool) {
			for _, focus := range source {
				//If yield returns false iteration must be stopped
				if !yield(focus) {
					break
				}
			}
		}
	},
	//lengthGetter
	func(source []int) int {
		return len(source)
	},
	//modify
	func(fmap func(focus int) int, source []int) []int {
		//modify functions must not alter the source they must return a modified copy
		var ret []int
		for _, focus := range source {
			ret = append(ret, fmap(focus))
		}
		return ret
	},
	ExprCustom("ExampleTraversal"),
)

result := MustModify(traverseSlice, Mul(10), []int{1, 2, 3})

fmt.Println(result)
Output:

[10 20 30]

func TraversalE

func TraversalE[S, A any](
	seq func(ctx context.Context, source S) iter.Seq2[A, error],
	lengthGetter LengthGetterFunc[S],
	modify func(ctx context.Context, fmap func(focus A) (A, error), source S) (S, error),
	exprDef ExpressionDef,
) Optic[int, S, S, A, A, ReturnMany, ReadWrite, UniDir, Err]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

A traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This traversal converts the elements of a string slice to ints, reporting any conversion errors encountered.
//It is non polymorphic so any modification actions still return a []string
parseInts := TraversalE[[]string, int](
	//iter
	func(ctx context.Context, source []string) iter.Seq2[int, error] {
		return func(yield func(focus int, err error) bool) {
			for _, strFocus := range source {
				intFocus, err := strconv.ParseInt(strFocus, 10, 32)
				//errors are reported to the caller by yielding. The caller can decide to stop iteration by returning false from the yield function.
				if !yield(int(intFocus), err) {
					//If yield returns false iteration must be stopped
					break
				}
			}
		}
	},
	//Length getter, nil will use the iterator to calculate the length
	nil,
	//modify
	func(ctx context.Context, fmap func(focus int) (int, error), source []string) ([]string, error) {
		//Modify functions must not alter the source they must return a modified copy
		//This traversal is non polymorphic so even though we convert the focus to ints we have to convert back to strings for the return
		var ret []string
		for _, strFocus := range source {
			intFocus, err := strconv.ParseInt(strFocus, 10, 32)
			if err != nil {
				//In contrast to iter modify function must fail the modify operation immediately otherwise the returned []string would be incomplete
				return nil, err
			}
			newVal, err := fmap(int(intFocus))
			if err != nil {
				//In contrast to iter modify function must fail the modify operation immediately otherwise the returned []string would be incomplete
				return nil, err
			}

			//This traversal is non polymorphic so we must convert back string
			ret = append(ret, strconv.Itoa(newVal))
		}

		return ret, nil
	},
	ExprCustom("ExampleTraversalR"),
)

//Note that result is an []string but the Mul operation acts on integer values
var result []string
result, err := Modify(parseInts, Mul[int](10), []string{"1", "2", "3"})

fmt.Println(result, err)

_, err = Modify(parseInts, Mul(10), []string{"1", "two", "3"})

fmt.Println(err.Error())
Output:

[10 20 30] <nil>
strconv.ParseInt: parsing "two": invalid syntax
optic error path:
	Custom(ExampleTraversalR)

func TraversalEP

func TraversalEP[S, T, A, B any](
	seq func(ctx context.Context, source S) iter.Seq2[A, error],
	lengthGetter LengthGetterFunc[S],
	modify func(ctx context.Context, fmap func(focus A) (B, error), source S) (T, error),
	exprDef ExpressionDef,
) Optic[int, S, T, A, B, ReturnMany, ReadWrite, UniDir, Err]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

A traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • expr: should return the expression type. See the expr package for more information.

See:

func TraversalI

func TraversalI[I, S, A any](
	iter func(source S) SeqI[I, A],
	lengthGetter func(source S) int,
	modify func(fmap func(index I, focus A) A, source S) S,
	ixget func(source S, index I) iter.Seq2[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadWrite, UniDir, Pure]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

An indexed traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This traversal iterates of the elements of an []int including the index of the element
traverseSlice := TraversalI[int, []int, int](
	//iter
	func(source []int) SeqI[int, int] {
		return func(yield func(index int, focus int) bool) {
			for index, focus := range source {
				//If yield returns false iteration must be stopped
				if !yield(index, focus) {
					break
				}
			}
		}
	},
	//length getter
	func(source []int) int {
		return len(source)
	},
	//modify
	func(fmap func(index int, focus int) int, source []int) []int {
		//modify functions must not alter the source they must return a modified copy
		var ret []int
		for index, focus := range source {
			ret = append(ret, fmap(index, focus))
		}
		return ret
	},
	func(source []int, index int) iter.Seq2[int, int] {
		return func(yield func(index int, focus int) bool) {
			yield(index, source[index])
		}
	},
	func(indexA, indexB int) bool {
		return indexA == indexB
	},
	ExprCustom("ExampleTraversalI"),
)

result := MustModifyI(traverseSlice, OpI(func(index int, focus int) int {
	return index * focus
}), []int{1, 2, 3})

fmt.Println(result)
Output:

[0 2 6]

func TraversalIE

func TraversalIE[I, S, A any](
	seq func(ctx context.Context, source S) SeqIE[I, A],
	lengthGetter LengthGetterFunc[S],
	modify func(ctx context.Context, fmap func(index I, focus A) (A, error), source S) (S, error),
	ixget func(ctx context.Context, index I, source S) SeqIE[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, S, A, A, ReturnMany, ReadWrite, UniDir, Err]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

An indexed traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

func TraversalIEP

func TraversalIEP[I, S, T, A, B any](
	seq func(ctx context.Context, source S) SeqIE[I, A],
	lengthGetter LengthGetterFunc[S],
	modify func(ctx context.Context, fmap func(index I, focus A) (B, error), source S) (T, error),
	ixget func(ctx context.Context, index I, source S) SeqIE[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnMany, ReadWrite, UniDir, Err]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

An indexed traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This traversal converts the elements of a string slice to ints, reporting any conversion errors encountered.
//It is polymorphic so is able to return an []int even through the source type is []string
parseInts := TraversalIEP[int, []string, []int, int, int](
	func(ctx context.Context, source []string) SeqIE[int, int] {
		return func(yield func(ValueIE[int, int]) bool) {
			for index, strFocus := range source {
				intFocus, err := strconv.ParseInt(strFocus, 10, 32)
				//errors are reported to the caller by yielding. The caller can decide to stop iteration by returning false from the yield function.
				if !yield(ValIE(index, int(intFocus), err)) {
					//If yield returns false iteration must be stopped
					break
				}
			}
		}
	},
	//Length getter nil will use the iteratoe function to calculate the length,
	nil,
	func(ctx context.Context, fmap func(index int, focus int) (int, error), source []string) ([]int, error) {
		var ret []int
		for index, strFocus := range source {
			intFocus, err := strconv.ParseInt(strFocus, 10, 32)
			if err != nil {
				//We must fail the modify operation immediately otherwise the returned []int would be incomplete
				return nil, err
			}
			newVal, err := fmap(index, int(intFocus))
			if err != nil {
				//We must fail the modify operation immediately otherwise the returned []int would be incomplete
				return nil, err
			}

			ret = append(ret, newVal)
		}

		return ret, nil
	},
	func(ctx context.Context, index int, source []string) SeqIE[int, int] {
		return func(yield func(ValueIE[int, int]) bool) {
			strFocus := source[index]
			intFocus, err := strconv.ParseInt(strFocus, 10, 32)
			//errors are reported to the caller by yielding. The caller can decide to stop iteration by returning false from the yield function.
			yield(ValIE(index, int(intFocus), err))
		}
	},
	IxMatchComparable[int](),
	ExprCustom("ExampleTraversalF"),
)

var result []int
result, err := Modify(parseInts, Mul(10), []string{"1", "2", "3"})

fmt.Println(result, err)

_, err = Modify(parseInts, Mul(10), []string{"1", "two", "3"})

fmt.Println(err.Error())
Output:

[10 20 30] <nil>
strconv.ParseInt: parsing "two": invalid syntax
optic error path:
	Custom(ExampleTraversalF)

func TraversalIP

func TraversalIP[I, S, T, A, B any](
	seq func(source S) SeqI[I, A],
	lengthGetter func(source S) int,
	modify func(fmap func(index I, focus A) B, source S) T,
	ixget func(source S, index I) iter.Seq2[I, A],
	ixMatch func(indexA, indexB I) bool,
	exprDef ExpressionDef,
) Optic[I, S, T, A, B, ReturnMany, ReadWrite, UniDir, Pure]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

An indexed traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • ixGet : should iterate over the values in the source with the given index.
  • ixMatch : should return true if the 2 index values are equal. Pass nil for a default implementation that calls the iter function.
  • expr: should return the expression type. See the expr package for more information.

See:

func TraversalP

func TraversalP[S, T, A, B any](
	seq func(source S) iter.Seq[A],
	lengthGetter func(source S) int,
	modify func(fmap func(focus A) B, source S) T,
	exprDef ExpressionDef,
) Optic[int, S, T, A, B, ReturnMany, ReadWrite, UniDir, Pure]

Constructor for a Traversal optic. Traversals focus on multiple elements.

The following Traversal constructors are available.

A traversal is constructed from 4 functions

  • iter : should iterates over the values in the source.
  • lengthGetter: should efficiently return the number of elements that will be focused. Pass nil for a default implementation that calls the iter function.
  • modify : should call fmap on each value in the source and return a new instance of the source type containing the mapped values.
  • expr: should return the expression type. See the expr package for more information.

See:

Example
//This traversal is polymorphic. It converts a slice of ints to float64s.
intToFloat := TraversalP[[]int, []float64, int, float64](
	//iter
	func(source []int) iter.Seq[int] {
		return func(yield func(focus int) bool) {
			//If yield returns false iteration must be stopped
			for _, focus := range source {
				if !yield(focus) {
					break
				}
			}
		}
	},
	//length getter
	func(source []int) int {
		return len(source)
	},
	//modify
	func(fmap func(focus int) float64, source []int) []float64 {
		//Modify functions must not alter the source they must return a modified copy
		var ret []float64
		for _, focus := range source {
			ret = append(ret, fmap(focus))
		}
		return ret
	},
	ExprCustom("ExampleTraversalP"),
)

result := MustModify(intToFloat, Op(func(focus int) float64 {
	return float64(focus) + 0.5
}), []int{1, 2, 3})

fmt.Println(result)
Output:

[1.5 2.5 3.5]

func TraverseCol

func TraverseCol[I comparable, A any]() Optic[I, Collection[I, A, Pure], Collection[I, A, Pure], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseCol returns an Traversal that focuses the elements of a collection.

See:

Example
col := ValCol(5, 10, 15)

result, err := Modify(
	TraverseCol[int, int](),
	Mul(10),
	col,
)
fmt.Println(result, err)
Output:

Col[0:50 1:100 2:150] <nil>

func TraverseColE

func TraverseColE[I comparable, A any, ERR any]() Optic[I, Collection[I, A, ERR], Collection[I, A, ERR], A, A, ReturnMany, ReadWrite, UniDir, ERR]

TraverseColE returns an Traversal that focuses the elements of a collection.

The modifyRetainErrors controls whether errors in the collection are maintained. true will return a collection with error entries, false will return the first error.

See:

  • TraverseCol for a simpler version that only supports comparable index types.
  • TraverseColI for a version that supports arbitrary index types.
  • TraverseColP for a polymorphic version
  • TraverseColEP for an impure,polymorphic version
  • TraverseColIEP for am impure,polymorphic version that supports arbitrary index types.
Example
col := ValColE(
	ValE(1, nil),
	ValE(0, errors.New("sabotage")),
	ValE(3, nil),
)

result, err := Modify(
	TraverseColE[int, int, Err](),
	Mul(10),
	col,
)
fmt.Println(result, err)
Output:

<nil> sabotage
optic error path:
	Traverse

func TraverseColEP

func TraverseColEP[I comparable, A, B any, ERR any]() Optic[I, Collection[I, A, ERR], Collection[I, B, ERR], A, B, ReturnMany, ReadWrite, UniDir, ERR]

TraverseColP returns an Traversal that focuses the elements of a collection.

See:

  • TraverseCol for a simpler version that only supports comparable index types.
  • TraverseColI for a version that supports arbitrary index types.
  • TraverseColE for an impure version
  • TraverseColEP for an impure,polymorphic version
  • TraverseColIEP for am impure,polymorphic version that supports arbitrary index types.
Example
col := ValColE(
	ValE("1", nil),
	ValE("", errors.New("sabotage")),
	ValE("3", nil),
)

result, err := Modify(
	Compose(
		TraverseColEP[int, string, int, Err](),
		ParseIntP[int](10, 0),
	),
	Mul(10),
	col,
)
fmt.Println(result, err)
Output:

<nil> sabotage
optic error path:
	Traverse

func TraverseColI

func TraverseColI[I, A any](ixmatch func(a, b I) bool) Optic[I, Collection[I, A, Pure], Collection[I, A, Pure], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseColI returns an Traversal that focuses the elements of a collection.

See:

Example
col := ValColI(
	func(a, b []int) bool { return a[0] == b[0] },
	ValI([]int{0}, 5),
	ValI([]int{1}, 10),
	ValI([]int{2}, 15),
)

result, err := Modify(
	TraverseColI[[]int, int](col.AsIxMatch()),
	Mul(10),
	col,
)
fmt.Println(result, err)
Output:

Col[[0]:50 [1]:100 [2]:150] <nil>

func TraverseColIE

func TraverseColIE[I, A, ERR any](ixmatch func(a, b I) bool) Optic[I, Collection[I, A, ERR], Collection[I, A, ERR], A, A, ReturnMany, ReadWrite, UniDir, ERR]

func TraverseColIEP

func TraverseColIEP[I, A, B, ERR any](ixmatch func(a, b I) bool) Optic[I, Collection[I, A, ERR], Collection[I, B, ERR], A, B, ReturnMany, ReadWrite, UniDir, ERR]

TraverseColIEP returns an Traversal that focuses the elements of a collection.

under Modification the returned collection is lazily evaluated. See

See:

Example
col := ValColE(
	ValE("1", nil),
	ValE("", errors.New("sabotage")),
	ValE("3", nil),
)

result, err := Modify(
	Compose(
		TraverseColIEP[int, string, int, Err](IxMatchComparable[int]()),
		ParseIntP[int](10, 0),
	),
	Mul(10),
	col,
)
fmt.Println(result, err)
Output:

<nil> sabotage
optic error path:
	Traverse

func TraverseColP

func TraverseColP[I comparable, A, B any]() Optic[I, Collection[I, A, Pure], Collection[I, B, Pure], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseColP returns an Traversal that focuses the elements of a collection.

See:

  • TraverseCol for a simpler version that only supports comparable index types.
  • TraverseColI for a version that supports arbitrary index types.
  • TraverseColE for an impure version
  • TraverseColEP for an impure,polymorphic version
  • TraverseColIEP for am impure,polymorphic version that supports arbitrary index types.
Example
col := ValCol("1", "2", "3")

var overResult Collection[int, int, Pure]
overResult, err := Modify(
	TraverseColP[int, string, int](),
	ParseInt[int](10, 32),
	col,
)
fmt.Println(overResult, err)
Output:

Col[0:1 1:2 2:3] <nil>

func TraverseColType

func TraverseColType[I, S, T, A, B any, ERR any](s CollectionType[I, S, T, A, B, ERR]) Optic[I, S, T, A, B, ReturnMany, ReadWrite, UniDir, ERR]

TraverseColType returns an optic that focuses the elements of the source collection.

Example
sliceCol := SliceColType[string]()

traverse := TraverseColType(sliceCol)

result := MustModify(
	traverse,
	Op(strings.ToUpper),
	[]string{"alpha", "beta", "gamma", "delta"},
)

fmt.Println(result)
Output:

[ALPHA BETA GAMMA DELTA]

func TraverseMap

func TraverseMap[K comparable, A any]() Optic[K, map[K]A, map[K]A, A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseMap returns a Traversal that focuses the elements of a map. The key of the map element is used as the index.

Note: TraverseMap always iterates in key order.

See: TraverseMapP for a polymorphic version

Example
mapData := map[string]int{
	"a": 5,
	"b": 10,
	"c": 15,
}

//Technically multiple elements of an Traversal may have the same index so Index returns multiple values. FirstOf selects the first one.
elemOf, found := MustGetFirst(Index(TraverseMap[string, int](), "b"), mapData)
fmt.Println(elemOf, found)

result := MustModify(TraverseMap[string, int](), Mul(10), mapData)
fmt.Println(result)
Output:

10 true
map[a:50 b:100 c:150]

func TraverseMapCol

func TraverseMapCol[K comparable, S any]() Optic[K, Collection[K, S, Pure], Collection[K, S, Pure], S, S, ReturnMany, ReadWrite, UniDir, Pure]

TraverseMapCol returns a Traversal over the Collection representation of a Map.

func TraverseMapP

func TraverseMapP[K comparable, A any, B any]() Optic[K, map[K]A, map[K]B, A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseMapP returns a polymorphic Traversal that focuses the elements of a map. The key of the map element is used as the index.

Note: TraverseMapP always iterates in key order.

See: TraverseMap for a non polymorphic version

Example
mapData := map[string]string{
	"a": "5",
	"b": "10",
	"c": "15",
}

//Not the result is a map[string]int not map[string]string
var overResult map[string]int = MustModify(TraverseMapP[string, string, int](), Op(func(focus string) int {
	i, _ := strconv.ParseInt(focus, 10, 32)
	return int(i)
}), mapData)
fmt.Println(overResult)
Output:

map[a:5 b:10 c:15]

func TraverseOption

func TraverseOption[A any]() Optic[Void, mo.Option[A], mo.Option[A], A, A, ReturnMany, ReadWrite, BiDir, Pure]

TraverseOption returns a Prism that matches on the Some value of a mo.Option. This has the effect of traversing the option ignoring None values.

This function is synonymous with Some

See:

  • None for a version matches on the None value.
  • Non for an optic that provides default values for None values.
Example
data := []mo.Option[int]{
	mo.Some(1),
	mo.None[int](),
	mo.Some(2),
}

//View actions like MustToSliceOf unwrap the option if possible and ignore the None elements.
var result []int = MustGet(SliceOf(Compose(TraverseSlice[mo.Option[int]](), TraverseOption[int]()), len(data)), data)
fmt.Println(result)

//Modification actions like over cause TraverseOption to skip over out the None elements and updates only the values that are present.
//The composed lense work together to return the original data structure []mo.Option[int] with the applied mapping.
var overResult []mo.Option[int] = MustModify(Compose(TraverseSlice[mo.Option[int]](), TraverseOption[int]()), Mul(10), data)
fmt.Println(overResult)
Output:

[1 2]
[{true 10} {false 0} {true 20}]

func TraversePtr

func TraversePtr[S any]() Optic[Void, *S, *S, S, S, ReturnMany, ReadWrite, BiDir, Pure]

func TraversePtrE

func TraversePtrE[S any]() Optic[Void, *S, *S, S, S, ReturnMany, ReadWrite, BiDir, Err]

func TraversePtrEP

func TraversePtrEP[S, T any]() Optic[Void, *S, *T, S, T, ReturnMany, ReadWrite, BiDir, Err]

func TraversePtrP

func TraversePtrP[S, T any]() Optic[Void, *S, *T, S, T, ReturnMany, ReadWrite, BiDir, Pure]

func TraverseSlice

func TraverseSlice[A any]() Optic[int, []A, []A, A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseSlice returns a Traversal that focuses on the elements of a slice.

See: TraverseSliceP for a polymorphic version

Example
slice := []int{5, 10, 15}

//Technically multiple elements of an Traversal may have the same index so Index focuses multiple values. MustGetFirst selects the first one.
elemOf, found := MustGetFirst(Index(TraverseSlice[int](), 1), slice)
fmt.Println(elemOf, found)

result := MustModify(TraverseSlice[int](), Mul(10), slice)
fmt.Println(result)
Output:

10 true
[50 100 150]

func TraverseSliceCol

func TraverseSliceCol[A any]() Optic[int, Collection[int, A, Pure], Collection[int, A, Pure], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseSliceCol returns a Traversal over the Collection representation of a Slice.

func TraverseSliceP

func TraverseSliceP[A, B any]() Optic[int, []A, []B, A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseSliceP returns a polymorphic Traversal that focuses on the elements of a slice.

See: TraverseSlice for a non polymorphic version

Example
slice := []string{"1", "2", "3"}

var overResult []int
overResult, err := Modify(
	TraverseSliceP[string, int](),
	ParseInt[int](10, 32),
	slice,
)
fmt.Println(overResult, err)
Output:

[1 2 3] <nil>

func TraverseString

func TraverseString() Optic[int, string, string, rune, rune, ReturnMany, ReadWrite, UniDir, Pure]

TraverseString returns an Traversal optic that focuses on the runes in a string.

See: - TraverseStringP for a version that supports aliases of string and rune

Example
element2, _ := MustGetFirst(Index(TraverseString(), 1), "example")
fmt.Println(string(element2))

//unicode.ToUpper operates on individual runes.
result := MustModify(TraverseString(), Op(unicode.ToUpper), "example")
fmt.Println(result)
Output:

x
EXAMPLE

func TraverseStringCol

TraverseStringCol returns a Traversal over the Collection representation of a String.

func TraverseStringP

func TraverseStringP[S ~string, R ~rune]() Optic[int, S, S, R, R, ReturnMany, ReadWrite, UniDir, Pure]

TraverseStringP returns an Traversal optic that focuses on the runes in a string.

See: - TraverseStringP for a simple version that doesn't support aliases of string and rune

func TraverseT2

func TraverseT2[A any]() Optic[int, lo.Tuple2[A, A], lo.Tuple2[A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT2 returns a Traversal focusing on the elements of a lo.Tuple2

See: TraverseT2P for a polymorphic version

Example
data := lo.T2[int, int](1, 2)

optic := TraverseT2[int]()

var viewResult []int = MustGet(SliceOf(optic, 2), data)
fmt.Println(viewResult)

var overResult lo.Tuple2[int, int] = MustModify(optic, Add(10), data)
fmt.Println(overResult)
Output:

[1 2]
{11 12}

func TraverseT2P

func TraverseT2P[A any, B any]() Optic[int, lo.Tuple2[A, A], lo.Tuple2[B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT2P returns a polymorphic Traversal focusing on the elements of a lo.Tuple2

See: TraverseT2 for a non polymorphic version

Example
data := lo.T2[string, string]("1", "2")

optic := Compose(TraverseT2P[string, int](), ParseIntP[int](10, 32))

var viewResult []int
var err error
viewResult, err = Get(SliceOfP(optic, 2), data)
fmt.Println(viewResult, err)

var overResult lo.Tuple2[int, int]
overResult, err = Modify(optic, Add(10), data)
fmt.Println(overResult, err)
Output:

[1 2] <nil>
{11 12} <nil>

func TraverseT3

func TraverseT3[A any]() Optic[int, lo.Tuple3[A, A, A], lo.Tuple3[A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT3 returns a Traversal focusing on the elements of a lo.Tuple3

See: TraverseT3P for a polymorphic version

func TraverseT3P

func TraverseT3P[A any, B any]() Optic[int, lo.Tuple3[A, A, A], lo.Tuple3[B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT3P returns a polymorphic Traversal focusing on the elements of a lo.Tuple3

See: TraverseT3 for a non polymorphic version

func TraverseT4

func TraverseT4[A any]() Optic[int, lo.Tuple4[A, A, A, A], lo.Tuple4[A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT4 returns a Traversal focusing on the elements of a lo.Tuple4

See: TraverseT4P for a polymorphic version

func TraverseT4P

func TraverseT4P[A any, B any]() Optic[int, lo.Tuple4[A, A, A, A], lo.Tuple4[B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT4P returns a polymorphic Traversal focusing on the elements of a lo.Tuple4

See: TraverseT4 for a non polymorphic version

func TraverseT5

func TraverseT5[A any]() Optic[int, lo.Tuple5[A, A, A, A, A], lo.Tuple5[A, A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT5 returns a Traversal focusing on the elements of a lo.Tuple5

See: TraverseT5P for a polymorphic version

func TraverseT5P

func TraverseT5P[A any, B any]() Optic[int, lo.Tuple5[A, A, A, A, A], lo.Tuple5[B, B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT5P returns a polymorphic Traversal focusing on the elements of a lo.Tuple5

See: TraverseT5 for a non polymorphic version

func TraverseT6

func TraverseT6[A any]() Optic[int, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[A, A, A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT6 returns a Traversal focusing on the elements of a lo.Tuple6

See: TraverseT6P for a polymorphic version

func TraverseT6P

func TraverseT6P[A any, B any]() Optic[int, lo.Tuple6[A, A, A, A, A, A], lo.Tuple6[B, B, B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT6P returns a polymorphic Traversal focusing on the elements of a lo.Tuple6

See: TraverseT6 for a non polymorphic version

func TraverseT7

func TraverseT7[A any]() Optic[int, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[A, A, A, A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT7 returns a Traversal focusing on the elements of a lo.Tuple7

See: TraverseT7P for a polymorphic version

func TraverseT7P

func TraverseT7P[A any, B any]() Optic[int, lo.Tuple7[A, A, A, A, A, A, A], lo.Tuple7[B, B, B, B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT7P returns a polymorphic Traversal focusing on the elements of a lo.Tuple7

See: TraverseT7 for a non polymorphic version

func TraverseT8

func TraverseT8[A any]() Optic[int, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[A, A, A, A, A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT8 returns a Traversal focusing on the elements of a lo.Tuple8

See: TraverseT8P for a polymorphic version

func TraverseT8P

func TraverseT8P[A any, B any]() Optic[int, lo.Tuple8[A, A, A, A, A, A, A, A], lo.Tuple8[B, B, B, B, B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT8P returns a polymorphic Traversal focusing on the elements of a lo.Tuple8

See: TraverseT8 for a non polymorphic version

func TraverseT9

func TraverseT9[A any]() Optic[int, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[A, A, A, A, A, A, A, A, A], A, A, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT9 returns a Traversal focusing on the elements of a lo.Tuple9

See: TraverseT9P for a polymorphic version

func TraverseT9P

func TraverseT9P[A any, B any]() Optic[int, lo.Tuple9[A, A, A, A, A, A, A, A, A], lo.Tuple9[B, B, B, B, B, B, B, B, B], A, B, ReturnMany, ReadWrite, UniDir, Pure]

TraverseT9P returns a polymorphic Traversal focusing on the elements of a lo.Tuple9

See: TraverseT9 for a non polymorphic version

func TrimmingWhile

func TrimmingWhile[I, S, T, A, RETI, RW any, DIR any, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The TrimmingWhile combinator skips leading and trailing elements until an element that does not match the predicate is found.

See TrimmingWhileI for an indexed version.

Example
data := "ooooooooleading and trailing o'sooooooooo"

optic := TrimmingWhile(TraverseString(), Eq('o'))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(string(listResult))

overResult := MustModify(optic, Op(unicode.ToUpper), data)
fmt.Println(overResult)
Output:

leading and trailing o's
ooooooooLEADING AND TRAILING O'Sooooooooo

func TrimmingWhileI

func TrimmingWhileI[I, S, T, A, RETI, RW any, DIR, ERR, ERRP any](o Optic[I, S, T, A, A, RETI, RW, DIR, ERR], pred PredicateI[I, A, ERRP]) Optic[I, S, T, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

The TrimmingWhileI combinator skips leading and trailing elements until an element that does not match the indexed predicate is found.

See TrimmingWhile for a non indexed version.

Example
data := "Lorem ipsum delor"

optic := TrimmingWhileI(

	TraverseString(), OpI(func(index int, focus rune) bool {
		return index < 6 || index > 10
	}))

listResult := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(string(listResult))

overResult := MustModify(optic, Op(unicode.ToUpper), data)
fmt.Println(overResult)
Output:

ipsum
Lorem IPSUM delor

func True

func True[A any]() Optic[Void, A, A, bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

True returns a Predicate that is always satisfied.

Example
data := []int{1, 2, 3, 4, 5}

filtered := MustGet(
	SliceOf(
		Filtered(

			TraverseSlice[int](), True[int](),
		),
		len(data),
	),
	data,
)
fmt.Println(filtered)
Output:

[1 2 3 4 5]

func Ud

func Ud[I, S, T, A, B any, RET any, RW any, DIR any, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, UniDir, ERR]

The Ud re-constrain converts an Optic with any direction type to UniDir

DIR any --> UniDir

See:

  • Bd for a re-constrain to BiDir
  • Ud for a re-constrain to UniDir
  • DirL for a re-constrain to the left side of a CompositionTree
  • DirR for a re-constrain to the Right side of a CompositionTree
  • DirSwap for a re-constrain that swaps the components of a CompositionTree
  • DirSwapL for a re-constrain that swaps the left components of a nested CompositionTree
  • DirSwapR for a re-constrain that swaps the right components of a nested CompositionTree
  • DirMerge for a re-constrain that merges identical components of a CompositionTree
  • DirMergeL for a re-constrain that merges the identical left components of a nested CompositionTree
  • DirMergeR for a re-constrain that merges the identical right components of a nested CompositionTree
  • DirTrans for a re-constrain that swaps the middle elements of a nested CompositionTree.
  • DirTransL for a re-constrain that swaps the right components into the left nested CompositionTree
  • DirTransR for a re-constrain that swaps the left components into the right nested CompositionTree
Example
var optic Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	CompositionTree[ReturnOne, ReturnOne],
	CompositionTree[ReadWrite, ReadWrite],
	CompositionTree[UniDir, BiDir],
	CompositionTree[Pure, Err],
] = Compose(
	T2B[int, string](),
	ParseInt[int](10, 32),
)

var reconstrained Optic[
	Void,
	lo.Tuple2[int, string],
	lo.Tuple2[int, string],
	int,
	int,
	ReturnOne,
	ReadWrite,
	UniDir,
	Err,
] = Ret1(Rw(Ud(EErr(optic))))

fmt.Println(reconstrained.OpticType())
Output:

Lens

func UnaryOp

func UnaryOp[S, A any](op func(S) A, exprOp string) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

UnaryOp returns an Operation version of the given unary operator function. This constructor is a convenience wrapper for Operator with a simpler expression parameter.

This should only be used for 1 way lossy operations. If the operation is reversible then use an Iso instead.

Example
//string length is non reversible so an iso cannot be used.
strLen := UnaryOp(func(val string) int { return len(val) }, "len")

data := []string{"alpha", "beta", "gamma", "delta", "epsilon", "zeta"}

var filtered []string = MustGet(SliceOf(Filtered(TraverseSlice[string](), Compose(strLen, Gt(4))), len(data)), data)
fmt.Println(filtered)

var strLens []int = MustGet(SliceOf(Compose(TraverseSlice[string](), strLen), len(data)), data)
fmt.Println(strLens)

var overResult []int = MustModify(TraverseSliceP[string, int](), strLen, data)
fmt.Println(overResult)
Output:

[alpha gamma delta epsilon]
[5 4 5 5 7 4]
[5 4 5 5 7 4]

func UnsafeOmni

func UnsafeOmni[I, S, T, A, B, RET, RW, DIR, ERR any](
	getter GetterFunc[I, S, A],
	setter SetterFunc[S, T, B],

	iter IterFunc[I, S, A],
	lengthGetter LengthGetterFunc[S],
	modify ModifyFunc[I, S, T, A, B],

	ixGetter IxGetterFunc[I, S, A],
	ixMatchFnc IxMatchFunc[I],

	reverseGetter ReverseGetterFunc[T, B],

	handler func(ctx context.Context) (ExprHandler, error),
	expression func() expr.OpticExpression,
) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

UnsafeOmni returns an optic using the given functions directly. UnsafeOmni optics should only be used when creating custom combinators.

Warning: The UnsafeOmni optic does not manage the OpticErrorPath this must be done manually using the OpticError method. Warning: The UnsafeOmni optic does not protect against unsafe iter functions (yield after break protection). Warning: The UnsafeOmni optic does not handle context deadlines and cancellation.

See:

  • Omni for a safe version

func UnsafeReconstrain

func UnsafeReconstrain[RET, RW, DIR, ERR, I, S, T, A, B, OLDRET, OLDRW, OLDDIR, OLDERR any](o Optic[I, S, T, A, B, OLDRET, OLDRW, OLDDIR, OLDERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

!!DANGER!! This function blindly applies the new constraints without regard to the current constraints. The resulting optic may return errors when an unimplemented optic function is called.

func UpCast

func UpCast[S, A any]() Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Pure]

UpCast returns an Operation that performs a safe type up cast from S to A. The cast is declared safe by the user. If the cast fails a panic will occur.

See:

  • DownCast for a pure version that ignores cast errors.
  • IsoCast for an Iso version.
Example
data := []int{1, 2, 3}

optic := Compose(TraverseSlice[int](), UpCast[int, any]()) //Casting int to any always succeeds this is a safe UpCast

var res []any = MustGet(SliceOf(optic, 3), data)
fmt.Println(res)

//WARNING: This is an unsafe UpCast and will cause a panic
//unsafeOptic := Compose(TraverseSlice[any](), UpCast[any, int]()) //Casting any to int may fail. In this case a panic will occur.
//var unsafeRes []int = MustGet(SliceOf(unsafeOptic, 3), []any{1, 2, 3})
//fmt.Println(unsafeRes)
Output:

[1 2 3]

func Value

func Value[S any](v S) Optic[Void, S, S, S, S, ReturnOne, ReadWrite, BiDir, Pure]

Value returns an optic that focuses the given value that can be changed under modification.

See:

  • Const for a polymorphic version that doesn't allow updates under modification
Example
data := "128"

specialParseInt := Compose(
	If(
		All(
			TraverseString(),
			Op(unicode.IsDigit),
		),
		Identity[string](),
		Value("-1"),
	),
	ParseInt[int](10, 0),
)

res, err := Modify(
	specialParseInt,
	Mul(10),
	data,
)

fmt.Println(res, err)

badData := "12°"

res, err = Modify(
	specialParseInt,
	Mul(10),
	badData,
)

fmt.Println(res, err)
Output:

1280 <nil>
-10 <nil>

func ValueEError

func ValueEError[T any]() Optic[Void, ValueE[T], ValueE[T], error, error, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the ValueE error field

func ValueEValue

func ValueEValue[T any]() Optic[Void, ValueE[T], ValueE[T], T, T, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the [ValueR] Value field

func ValueIEError

func ValueIEError[I, T any]() Optic[Void, ValueIE[I, T], ValueIE[I, T], error, error, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the ValueE error field

func ValueIEIndex

func ValueIEIndex[I, T any]() Optic[Void, ValueIE[I, T], ValueIE[I, T], I, I, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the [ValueR] Value field

func ValueIEValue

func ValueIEValue[I, T any]() Optic[Void, ValueIE[I, T], ValueIE[I, T], T, T, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the [ValueR] Value field

func ValueIIndex

func ValueIIndex[I, T any]() Optic[Void, ValueI[I, T], ValueI[I, T], I, I, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the ValueI Index field

func ValueIValue

func ValueIValue[I, T any]() Optic[Void, ValueI[I, T], ValueI[I, T], T, T, ReturnOne, ReadWrite, UniDir, Pure]

Lens for the ValueI Value field

func Var

func Var[S, A any](name string) Optic[Void, S, S, A, A, ReturnOne, ReadOnly, UniDir, Err]

Var is an Operator that focuses the value of the variable.

Note: if the variable is not defined an ErrVariableNotDefined will be returned.

Example
data := lo.T2(10, []int{1, 2, 3})

result, err := Get(
	SliceOf(
		WithVar(
			Compose3(
				T2B[int, []int](),
				TraverseSlice[int](),
				AddOp(
					Var[int, int]("a"),
					Identity[int](),
				),
			),
			"a",
			T2A[int, []int](),
		),
		3,
	),
	data,
)
fmt.Println(result, err)
Output:

[11 12 13] <nil>

func WithComprehension

func WithComprehension[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, []T, A, []B, RET, RW, DIR, ERR]

The WithComprehension combinator returns an applicative optic that modifies the given optic to perform a comprehension over the slice of return focuses.

Example
data := []string{"alpha", "beta"}

//The WithComprehension modifies this the optic to return an [][]string
optic := WithComprehension(TraverseSlice[string]())

//View actions are identical to the non applicative version of the optic.

//Modification actions have a slice as the return value
var overResult [][]string = MustModify(optic, Op(func(focus string) []string {
	return []string{
		focus + "-quadrant",
		focus + "-test",
	}
}), data)

//In the result every focused value is combined with each value in the return slice in every possible combination.
fmt.Println(overResult)

//WithComprehension also works with composed optics

composedData := []lo.Tuple2[string, string]{
	lo.T2("1", "alpha"),
	lo.T2("2", "beta"),
}

composedOptic := Compose(
	TraverseSlice[lo.Tuple2[string, string]](),
	T2B[string, string](),
)

composedFuncOptic := WithComprehension(composedOptic)

var composedResult [][]lo.Tuple2[string, string] = MustModify(composedFuncOptic, Op(func(focus string) []string {
	return []string{
		focus + "-quadrant",
		focus + "-test",
	}
}), composedData)
fmt.Println(composedResult)
Output:

[[alpha-quadrant beta-quadrant] [alpha-quadrant beta-test] [alpha-test beta-quadrant] [alpha-test beta-test]]
[[{1 alpha-quadrant} {2 beta-quadrant}] [{1 alpha-quadrant} {2 beta-test}] [{1 alpha-test} {2 beta-quadrant}] [{1 alpha-test} {2 beta-test}]]

func WithEither

func WithEither[P, I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, mo.Either[P, T], A, mo.Either[P, B], RET, RW, DIR, ERR]

The WithEither combinator returns an applicative optic enabling the return of an Either value. under modification

  • if any focus is left then the result is short circuited to this left value.
  • if the source is empty then the result is converted to the default left value.
Example
goodData := []string{"1", "2", "3", "4"}
badData := []string{"1", "2", "three", "four"}

//TraverseSliceP normally converts from []string to []int
//The AWithEither modifies this to mo.Either[string,[]int]
baseOptic := TraverseSliceP[string, int]()
optionOptic := WithEither[string](baseOptic)

//View actions are identical to the non applicative version of the optic.

//Modification actions have an either return value.
var goodOverResult mo.Either[string, []int] = MustModify(optionOptic, Op(func(focus string) mo.Either[string, int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	if err != nil {
		//We can use the left value to report the invalid string
		return mo.Left[string, int](focus)
	} else {
		return mo.Right[string, int](int(i))
	}
}), goodData)
fmt.Println(goodOverResult)

var badOverResult mo.Either[string, []int] = MustModify(optionOptic, Op(func(focus string) mo.Either[string, int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	if err != nil {
		//We can use the left value to report the invalid string
		return mo.Left[string, int](focus)
	} else {
		return mo.Right[string, int](int(i))
	}
}), badData)
fmt.Println(badOverResult)
Output:

{false  [1 2 3 4]}
{true three []}

func WithFunc

func WithFunc[P, I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, func(P) (T, error), A, func(P) (B, error), RET, RW, DIR, ERR]

The WithFunc combinator returns an applicative optic that enables the passing of a parameter into the optic.

Example
data := []string{"alpha", "beta", "gamma", "delta"}

//The WithFunc modifies this the optic to return a Func(string) []string
optic := WithFunc[string](TraverseSlice[string]())

//View actions are identical to the non applicative version of the optic.

//Modification actions have a func as the return value

var overResult func(string) ([]string, error) = MustModify(optic, Op(func(focus string) func(string) (string, error) {
	return func(param string) (string, error) {
		return focus + "-" + param, nil
	}
}), data)

//Calling the return funcion passes the given parameter into the over action.
fmt.Println(overResult("quadrant"))
fmt.Println(overResult("test"))

//WithFunc also works with composed optics

composedData := []lo.Tuple2[string, string]{
	lo.T2("1", "alpha"),
	lo.T2("2", "beta"),
	lo.T2("3", "gamma"),
	lo.T2("4", "delta"),
}

composedOptic := Compose(
	TraverseSlice[lo.Tuple2[string, string]](),
	T2B[string, string](),
)

composedFuncOptic := WithFunc[string](composedOptic)

var composedResult func(string) ([]lo.Tuple2[string, string], error) = MustModify(composedFuncOptic, Op(func(focus string) func(string) (string, error) {
	return func(param string) (string, error) {
		return focus + "-" + param, nil
	}
}), composedData)
fmt.Println(composedResult("quadrant"))
Output:

[alpha-quadrant beta-quadrant gamma-quadrant delta-quadrant] <nil>
[alpha-test beta-test gamma-test delta-test] <nil>
[{1 alpha-quadrant} {2 beta-quadrant} {3 gamma-quadrant} {4 delta-quadrant}] <nil>

func WithIndex

func WithIndex[I, S, T, A, B, RETI, RW, DIR, ERR any](o Optic[I, S, T, A, B, RETI, RW, DIR, ERR]) Optic[I, S, T, ValueI[I, A], ValueI[I, B], RETI, RW, UniDir, ERR]

The WithIndex combinator returns an optic that lifts the index value into a combined focus with the original focused value..

Note: Modifying the ValueIE index is not supported. The original index will be retained.

Example
data := map[string]int{
	"alpha": 1,
	"beta":  2,
	"gamma": 3,
	"delta": 4,
}

optic := SliceOf(WithIndex(TraverseMap[string, int]()), len(data))

var result []ValueI[string, int] = MustGet(optic, data)

fmt.Println(result)
Output:

[alpha:1 beta:2 delta:4 gamma:3]

func WithLogging

func WithLogging[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, ERR]
Example
data := []string{"alpha", "beta", "gamma", "delta"}

result := MustModify(
	WithLogging(
		TraverseSlice[string](),
	),
	Op(strings.ToUpper),
	data,
)

fmt.Println(result)
Output:

[ALPHA BETA GAMMA DELTA]

func WithMetrics

func WithMetrics[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR], m *Metrics) Optic[I, S, T, A, B, RET, RW, DIR, ERR]

The WithMetrics combinator returns an Optic that provides metrics to the given Metrics struct

See:

  • `IncCustomMetric` for a function that enables custom metrics to be published.
Example
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var metrics Metrics

res, ok := MustGetFirst(
	Reduce(
		WithMetrics(
			TraverseSlice[int](),
			&metrics,
		),
		Sum[int](),
	),
	data,
)

fmt.Println(res, ok)
fmt.Println(metrics)
Output:

55 true
metrics[F:10 A:1 I:0 L:0 Custom:map[]]

func WithOption

func WithOption[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, mo.Option[T], A, mo.Option[B], RET, RW, DIR, ERR]

The WithOption combinator returns an applicative optic enabling the return of optional values. under modification

  • if any focus is None then the result is short circuited to None.
  • if the source is empty then the result is converted to None.
Example
goodData := []string{"1", "2", "3", "4"}
badData := []string{"1", "2", "three", "4"}

//TraverseSliceP normally converts from []string to []int
//The WithOption modifies this to mo.Option[[]int]
baseOptic := TraverseSliceP[string, int]()
optionOptic := WithOption(baseOptic)

//View actions are identical to the non applicative version of the optic.

//Modification actions have optional return values.

var goodOverResult mo.Option[[]int] = MustModify(optionOptic, Op(func(focus string) mo.Option[int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	//Each return is also now an option
	//The first none option will cause the final result to short circuit to none
	return mo.TupleToOption(int(i), err == nil)
}), goodData)
fmt.Println(goodOverResult.Get())

var badOverResult mo.Option[[]int] = MustModify(optionOptic, Op(func(focus string) mo.Option[int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	//Each return is also now an option
	//The first none option will cause the final result to short circuit to none
	return mo.TupleToOption(int(i), err == nil)
}), badData)
fmt.Println(badOverResult.Get())

//WithOption also works with composed optics

composedData := []lo.Tuple2[string, string]{
	lo.T2("1", "alpha"),
	lo.T2("2", "beta"),
	lo.T2("3", "gamma"),
	lo.T2("4", "delta"),
}

composedOptic := Compose(
	TraverseSliceP[lo.Tuple2[string, string], lo.Tuple2[int, string]](),
	T2AP[string, string, int](),
)

composedOptionOptic := WithOption(composedOptic)

var goodComposedResult mo.Option[[]lo.Tuple2[int, string]] = MustModify(composedOptionOptic, Op(func(focus string) mo.Option[int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	//Each return is also now an option
	//The first none option will cause the final result to short circuit to none
	return mo.TupleToOption(int(i), err == nil)
}), composedData)
fmt.Println(goodComposedResult.Get())
Output:

[1 2 3 4] true
[] false
[{1 alpha} {2 beta} {3 gamma} {4 delta}] true

func WithPanic

func WithPanic[I, S, T, A, B, RET, RW, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, T, A, B, RET, RW, DIR, Pure]

func WithValidation

func WithValidation[V, I, S, T, A, B, RET, RW any, DIR, ERR any](o Optic[I, S, T, A, B, RET, RW, DIR, ERR]) Optic[I, S, mo.Either[[]V, T], A, mo.Either[V, B], RET, RW, DIR, ERR]

The WithValidation combinator returns an applicative optic able to report multiple validation errors.

Example
goodData := []string{"1", "2", "3", "4"}
badData := []string{"1", "2", "three", "four"}

//TraverseSliceP normally converts from []string to []int
//The WithValidation modifies this to mo.Either[[]string,[]int]
baseOptic := TraverseSliceP[string, int]()
optionOptic := WithValidation[string](baseOptic)

//View actions are identical to the non applicative version of the optic.

//Modification actions have an either return value.
var goodOverResult mo.Either[[]string, []int] = MustModify(optionOptic, Op(func(focus string) mo.Either[string, int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	if err != nil {
		//We can use the left value to report the invalid string
		return mo.Left[string, int](focus)
	} else {
		return mo.Right[string, int](int(i))
	}
}), goodData)
fmt.Println(goodOverResult)

var badOverResult mo.Either[[]string, []int] = MustModify(optionOptic, Op(func(focus string) mo.Either[string, int] {
	i, err := strconv.ParseInt(focus, 10, 32)
	if err != nil {
		//We can use the left value to report the invalid string
		return mo.Left[string, int](focus)
	} else {
		return mo.Right[string, int](int(i))
	}
}), badData)
fmt.Println(badOverResult)
Output:

{false [] [1 2 3 4]}
{true [three four] []}

func WithVar

func WithVar[I, S, T, A, B any, RET any, RW, DIR, ERR any, V any, VRET TReturnOne, VERR any](withVar Optic[I, S, T, A, B, RET, RW, DIR, ERR], name string, value Operation[S, V, VRET, VERR]) Optic[I, S, T, A, B, RET, RW, UniDir, CompositionTree[ERR, VERR]]

The WithVar combinator creates a named variable that is accessible inside the withVar optic.

See:

  • Var for a n optic that focuses the value of the variable.
Example
data := lo.T2(10, []int{1, 2, 3})

result, err := Get(
	SliceOf(
		WithVar(
			Compose3(
				T2B[int, []int](),
				TraverseSlice[int](),
				AddOp(
					Var[int, int]("a"),
					Identity[int](),
				),
			),
			"a",
			T2A[int, []int](),
		),
		3,
	),
	data,
)
fmt.Println(result, err)
Output:

[11 12 13] <nil>

func Worded

Worded returns a Traversal over the words in the source string.

See: - []

Example
numWords := MustGet(Length(Worded()), "Lorem  Ipsum    Dolor    Sit    Amet")
fmt.Println(numWords)

//Note that all white space is converted to a single space rune in the result
result := MustModifyI(Worded(), OpI(func(index int, word string) string {
	if index%2 == 0 {
		return strings.ToUpper(word) //Convert even indexed words to uppercase
	} else {
		return strings.ToLower(word) //Convert odd indexed words to lowercase
	}

}), "Lorem  Ipsum    Dolor    Sit    Amet")
fmt.Println(result)
Output:

5
LOREM  ipsum    DOLOR    sit    AMET

type OpticErrorPath

type OpticErrorPath struct {
	// contains filtered or unexported fields
}

OpticErrorPath is an error type that is joined with any error returned from an action. It contains the path to the optic where the error occurred. It can be extracted from the error using errors.As

func (*OpticErrorPath) Error

func (err *OpticErrorPath) Error() string

type OpticRO

type OpticRO[I, S, A, RET, RW, DIR, ERR any] interface {
	// Provides this optics [Iteration] style view function.
	// This methods behavior is defined for all optic types
	AsIter() IterFunc[I, S, A]

	// Provides this optics [Operation] style view function.
	// This methods behavior is only defined for [ReturnOne] optics.
	AsGetter() GetterFunc[I, S, A]

	// Provides this optics [Traversal] style view by index function.
	// This methods behavior is only defined for all optics.
	AsIxGetter() IxGetterFunc[I, S, A]

	AsIxMatch() IxMatchFunc[I]

	// Provides this optics [Iteration] style length getter function.
	// This methods behavior is defined for all optic types
	AsLengthGetter() LengthGetterFunc[S]

	AsOpGet() OpGetFunc[S, A]

	// Provides this optics expression tree representation.
	AsExpr() expr.OpticExpression

	//Provides the custom expression handler. Used by non go backends to execute expressions
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)

	// Provides this optics internal type. This indicates which methods have efficient implementations.
	OpticType() expr.OpticType

	// Indicates whether this optic returns exactly 1 result [ReturnOne] or 0 or more [ReturnMany]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [ReturnMany]
	// optic is passed to an action that requires a [ReturnOne] result. e.g. [View].
	ReturnType() RET

	// Indicates whether this optic supports modification [ReadWrite] or can only be viewed [ReadOnly]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [ReadOnly]
	// optic is passed to a modification action e.g. [Over].
	ReadWriteType() RW

	// Indicates whether this optic supports ReverseGet [BiDir] or is unidirectional [UniDir]
	// or was composed of several optics [CompositionTree]. Used to prevent compilation if a [UniDir]
	// optic is passed to an action requiring a reverseget e.g. [ReView].
	DirType() DIR

	ErrType() ERR
}

type OrderByPredicate

type OrderByPredicate[A, ERR any] Predicate[lo.Tuple2[A, A], ERR]

The OrderByPredicate interface is a simplified read only version of the Optic interface used for sorting. OrderByPredicates should return true if the left value is less than the right value

func OrderByOp

func OrderByOp[A any](less func(valueLeft A, valueRight A) bool) OrderByPredicate[A, Pure]

Constructor for an OrderByPredicate optic. This constructor is a convenience wrapper for Operator without an expression parameter.

The less function should return true if valueLeft is less than valueRight.

The following additional constructors are available.

See:

Example
data := []int{1, 10, 2, 9, 3, 8, 4, 7, 5, 6}

optic := Ordered(
	TraverseSlice[int](),
	OrderByOp(
		func(left, right int) bool {
			return left < right
		},
	),
)

result := MustGet(SliceOf(optic, len(data)), data)
fmt.Println(result)
Output:

[1 2 3 4 5 6 7 8 9 10]

type OrderByPredicateI

type OrderByPredicateI[I, A, ERR any] Predicate[lo.Tuple2[ValueI[I, A], ValueI[I, A]], ERR]

The OrderByPredicateI interface is a simplified read only version of the Optic interface used for sorting. OrderByIxPredicates should return true if the left value is less than the right value

type Predicate

type Predicate[S any, ERR any] interface {
	AsOpGet() OpGetFunc[S, bool]
	ErrType() ERR
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)
	AsExpr() expr.OpticExpression
}

A Predicate is an Operation that return true is the predicate is satisfied.

type PredicateE

type PredicateE[S any] interface {
	AsOpGet() OpGetFunc[S, bool]
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)
	AsExpr() expr.OpticExpression
}

A PredicateE is a variant of Predicate where it should be assumed an error is returned. This interface can be used to implement fluent style APIs at the cost of no longer being pure.

type PredicateI

type PredicateI[I, A, ERR any] Predicate[ValueI[I, A], ERR]

An PredicateI is an OperationI that return true if the index aware predicate is satisfied.

type PredicateIE

type PredicateIE[I, A any] PredicateE[ValueI[I, A]]

An PredicateIE is an PredicateI where it should be assumed an error is returned. This interface can be used to implement fluent style APIs at the cost of no longer being pure.

type Pure

type Pure Void

type ReadOnly

type ReadOnly []Void

Indicates this optic is read only. Used to prevent compilation when passing a ReadOnly optic to a ReadWrite action e.g. Modify

type ReadWrite

type ReadWrite Void

Indicates this optic supports read and write actions.

type Real

type Real interface {
	constraints.Float | constraints.Integer
}

Type constraint for types than be operated on by basic arithmetic operations like +,-./,* This type constraint excludes the complex types. See Arithmetic for a type constraint with complex types.

type ReducerExpressionDef

type ReducerExpressionDef struct {
	// contains filtered or unexported fields
}

func ReducerExprCustom

func ReducerExprCustom(id string) ReducerExpressionDef

func ReducerExprDef

func ReducerExprDef(
	expression func(t expr.ReducerTypeExpr) expr.ReducerExpression,
	subOptics ...asExprHandler,
) ReducerExpressionDef

func ReducerExprDefVarArgs

func ReducerExprDefVarArgs[T asExprHandler](
	expression func(t expr.ReducerTypeExpr) expr.ReducerExpression,
	subOptics ...T,
) ReducerExpressionDef

func ReducerExprTODO

func ReducerExprTODO(id string) ReducerExpressionDef

type Reduction

type Reduction[S, ERR any] ReductionP[S, S, S, ERR]

Reduction is non polymorphic interface that reduces multiple values into a single result.

For a polymorphic version see ReductionP

  • The Empty method should return a value for the initial state of the Reducer. e.g. 0 for sum and 1 for product.
  • The Reduce method should combine the 2 values and return a new combined result. e.g a+b for sum and a*b for product.
  • AsExpr should return the expression type. See the expr package for more information.

func MaxReducer

func MaxReducer[T cmp.Ordered]() Reduction[T, Pure]

MaxReducer returns a Reducer that returns the maximum of all focused elements.

See

  • Max for the non Reducer version.
  • [MaxReducerI] for a version that also returns the index.
Example
data := []int{1, 2, 30, 4}

product, ok := MustGetFirst(Reduce(TraverseSlice[int](), MaxReducer[int]()), data)

fmt.Println(product, ok)

//If there are no elements to  calculate the maximum of then false is returned
_, ok = MustGetFirst(Reduce(TraverseSlice[int](), MaxReducer[int]()), []int{})

fmt.Println(ok)
Output:

30 true
false

func MinReducer

func MinReducer[T Real]() Reduction[T, Pure]

MinReducer returns a Reducer that returns the minimum value.

See:

  • Min for the non Reducer version.
  • [MinReducerI] for a version that also returns the index.
Example
data := []int{10, 20, 3, 40}

min, ok := MustGetFirst(Reduce(TraverseSlice[int](), MinReducer[int]()), data)

fmt.Println(min, ok)

//If there are no elements to  calculate he minimum of then false is returned
_, ok = MustGetFirst(Reduce(TraverseSlice[int](), MinReducer[int]()), []int{})

fmt.Println(ok)
Output:

3 true
false

func Product

func Product[T Arithmetic]() Reduction[T, Pure]

Product returns a Reducer that multiplies all the focused elements.

See Mul for the non Reducer version.

Example
data := []int{1, 2, 3, 4}

product, ok := MustGetFirst(Reduce(TraverseSlice[int](), Product[int]()), data)

fmt.Println(product, ok)
Output:

24 true

func Reducer

func Reducer[A any](
	empty func() A,
	append func(state, appendVal A) A,
	expr ReducerExpressionDef,
) Reduction[A, Pure]
Example
data := []int{1, 2, 3}

var reducer Reduction[int, Pure] = Reducer[int](
	func() int {
		return 0
	},
	func(state, appendVal int) int {
		return state + appendVal
	},
	ReducerExprCustom("ExampleReducer"),
)

//Reduce applies the Reducer to the given optic and returns the aggregated value.
var res int
var ok bool
res, ok = MustGetFirst(Reduce(TraverseSlice[int](), reducer), data)

fmt.Println(res, ok)
Output:

6 true

func ReducerE

func ReducerE[A any](
	empty func(ctx context.Context) (A, error),
	append func(ctx context.Context, state, appendVal A) (A, error),
	expression ReducerExpressionDef,
) Reduction[A, Err]

func Sum

func Sum[T Arithmetic]() Reduction[T, Pure]

Sum returns a Reducer that sums all the focused elements.

See Add for the non Reducer version.

Example
data := []int{1, 2, 3, 4}

sum, ok := MustGetFirst(Reduce(TraverseSlice[int](), Sum[int]()), data)

fmt.Println(sum, ok)
Output:

10 true

type ReductionP

type ReductionP[S, E, R, ERR any] interface {
	Empty(ctx context.Context) (S, error)
	Reduce(ctx context.Context, a S, b E) (S, error)
	End(ctx context.Context, s S) (R, error)
	ErrType() ERR
	AsExpr() expr.ReducerExpression
	AsExprHandler() func(ctx context.Context) (ExprHandler, error)
}

ReducerP is a polymorphic interface that reduces multiple values into a single result.

For a non polymorphic version see ReducerP The S type parameter is the internal state that will be appended to. The E type parameter is the type of values that will be reduced. The R type parameter is the final result type.

  • The Empty method should return an initial state of the Reducer. e.g. 0 for sum and 1 for product.
  • The Reduce method should combine the previous state with a new value and return a new combined state. e.g a+b for sum and a*b for product.
  • The End method should extract the final result from the state.
  • AsExpr should return the expression type. See the expr package for more information.

func AppendSliceReducer

func AppendSliceReducer[T any](cap int) ReductionP[[]T, T, []T, Pure]

AppendSliceReducer retuens a reducer that appends the elements to a slice.

func AsReducer

func AsReducer[S, E any, RET TReturnOne, ERR any](empty S, reduce Operation[lo.Tuple2[S, E], S, RET, ERR]) ReductionP[S, E, S, ERR]

AsReducer returns a Reducer from an Operation function. like Add

  • empty is the initial value
  • reduce is the operation function to use as the append operation

See:

  • AsReducerP for a version that supports end transformations.
Example
data := []float64{2, 3, 4}

//A naive implementation of a mean function.
naiveMean := BinaryOp(
	func(a, b float64) float64 {
		return (a + b) / 2.0
	},
	"ExampleAsReducer",
)

meanReducer := AsReducer(0.0, naiveMean)

result, ok := MustGetFirst(Reduce(TraverseSlice[float64](), meanReducer), data)

fmt.Println(result, ok)
Output:

3 true

func AsReducerP

func AsReducerP[S, E, R any, EMRET, RET, ERET TReturnOne, EMERR, ERR any, EERR TPure](empty Operation[Void, S, EMRET, EMERR], reduce Operation[lo.Tuple2[S, E], S, RET, ERR], end Operation[S, R, ERET, EERR]) ReductionP[S, E, R, ERR]

AsReducerP returns a Reducer from an Operation function. like Add

  • empty is the initial value
  • reduce is the operation function to use as the append operation
  • end is the operation to transform the state to the final result type.

func CombiReducer

func CombiReducer[ERR, S, E, R any](
	empty func(ctx context.Context) (S, error),
	append func(ctx context.Context, state S, appendVal E) (S, error),
	end func(ctx context.Context, state S) (R, error),
	expression ReducerExpressionDef,
) ReductionP[S, E, R, ERR]

func FirstReducer

func FirstReducer[T any]() ReductionP[mo.Option[T], T, T, Pure]

FirstReducer returns a Reducer that reduces to the first element.

Example
data := []int{1, 2, 3, 4, 5, 6, 4, 3, 2, 1, 4}

res, err := Get(
	SliceOf(
		Grouped(
			SelfIndex(TraverseSlice[int](), EqT2[int]()),
			FirstReducer[int](),
		),
		len(data),
	),
	data,
)

fmt.Println(res, err)
Output:

[1 2 3 4 5 6] <nil>

func LastReducer

func LastReducer[T any]() ReductionP[mo.Option[T], T, T, Pure]

LastReducer returns a Reducer that reduces to the last element.

func Mean

func Mean[T Real]() ReductionP[lo.Tuple2[T, int], T, T, Pure]

Mean returns a Reducer that calculates the mean value.

Example
data := []float64{1, 1, 1, 20, 40, 45, 50}

mean, ok := MustGetFirst(Reduce(TraverseSlice[float64](), Mean[float64]()), data)

fmt.Println(mean, ok)
Output:

22.571428571428573 true

func Median

func Median[T Real]() ReductionP[medianState[T], T, T, Pure]

Median returns a Reducer that calculates the median value.

Example
data := []float64{1, 2, 3, 20, 40, 45, 50}

median, ok := MustGetFirst(Reduce(TraverseSlice[float64](), Median[float64]()), data)

fmt.Println(median, ok)
Output:

20 true

func Mode

func Mode[T cmp.Ordered]() ReductionP[map[T]int, T, T, Pure]

Mode returns a Reducer that calculates the modal value.

Example
data := []float64{1, 1, 1, 20, 40, 45, 50}

median, ok := MustGetFirst(Reduce(TraverseSlice[float64](), Mode[float64]()), data)

fmt.Println(median, ok)
Output:

1 true

func ReducerEP

func ReducerEP[S, E, R any](
	empty func(ctx context.Context) (S, error),
	append func(ctx context.Context, state S, appendVal E) (S, error),
	end func(ctx context.Context, state S) (R, error),
	expression ReducerExpressionDef,
) ReductionP[S, E, R, Err]

func ReducerP

func ReducerP[S, E, R any](
	empty func() S,
	append func(state S, appendVal E) S,
	end func(state S) R,
	expression ReducerExpressionDef,
) ReductionP[S, E, R, Pure]

func ReducerT2

func ReducerT2[SA, A, RA, SB, B, RB any, ERRA, ERRB any](ma ReductionP[SA, A, RA, ERRA], mb ReductionP[SB, B, RB, ERRB]) ReductionP[lo.Tuple2[SA, SB], lo.Tuple2[A, B], lo.Tuple2[RA, RB], CompositionTree[ERRA, ERRB]]

ReducerT2 returns a composite ReducerP enabling 2 aggregations to be executed in a single pass.

For a 3 value variant see ReducerT3

Example
data := []int{10, 20, 30}

compositeReducer := ReducerT2(Sum[int](), Product[int]())

//This optic takes slice of single ints and converts it to slice of lo.Tuple2[int,int] where A and B have duplicated values.
optic := Compose(TraverseSlice[int](), DupT2[int]())

//Reduce applies both Reducers at the same time and returns a lo.Tuple2 with the aggregated results.
var res lo.Tuple2[int, int]
var ok bool
res, ok = MustGetFirst(Reduce(optic, compositeReducer), data)

fmt.Println(res, ok)
Output:

{60 6000} true

func ReducerT3

func ReducerT3[SA, A, RA, SB, B, RB, SC, C, RC any, ERRA, ERRB, ERRC any](ma ReductionP[SA, A, RA, ERRA], mb ReductionP[SB, B, RB, ERRB], mc ReductionP[SC, C, RC, ERRC]) ReductionP[lo.Tuple3[SA, SB, SC], lo.Tuple3[A, B, C], lo.Tuple3[RA, RB, RC], CompositionTree[CompositionTree[ERRA, ERRB], ERRC]]

ReducerT3 returns a composite ReducerP enabling 3 aggregations to be executed in a single pass.

For a 2 value variant see ReducerT2

Example
data := []int{10, 20, 30}

compositeReducer := ReducerT3(Sum[int](), Product[int](), MaxReducer[int]())

//This optic takes slice of single ints and converts it to slice of lo.Tuple2[int,int] where A and B have duplicated values.
optic := Compose(TraverseSlice[int](), DupT3[int]())

//Reduce applies all Reducers at the same time and returns a lo.Tuple3 with the aggregated results.
var res lo.Tuple3[int, int, int]
var ok bool
res, ok = MustGetFirst(Reduce(optic, compositeReducer), data)

fmt.Println(res, ok)
Output:

{60 6000 30} true

func StringBuilderReducer

func StringBuilderReducer() ReductionP[*strings.Builder, string, string, Pure]

StringBuilderReducer returns a reducer which appends the elements.

Example
data := []string{"alpha", "bet"}

res, ok := MustGetFirst(
	Reduce(
		TraverseSlice[string](),
		StringBuilderReducer(),
	),
	data,
)
fmt.Println(res, ok)
Output:

alphabet true

type ReturnMany

type ReturnMany []Void

Indicates this optic returns exactly zero or more results.

type ReturnOne

type ReturnOne Void

Indicates this optic returns exactly one result. Used to prevent compilation when passing a ReturnMany optic to a ReturnOne action e.g. [View]

type ReverseGetterFunc

type ReverseGetterFunc[T, B any] func(ctx context.Context, focus B) (T, error)

Reverse conversion function for Iso and Prism type optics

type SeqE

type SeqE[A any] iter.Seq[ValueE[A]]

Push style iterator for error and value

Note: error is first to avoid it being ignored.

func (SeqE[A]) String

func (s SeqE[A]) String() string

type SeqI

type SeqI[I, A any] iter.Seq2[I, A]

Push style iterator for index and value

func (SeqI[I, A]) String

func (s SeqI[I, A]) String() string

type SeqIE

type SeqIE[I any, A any] iter.Seq[ValueIE[I, A]]

Push style iterator for index,value and error.

func (SeqIE[I, A]) MarshalJSON

func (s SeqIE[I, A]) MarshalJSON() ([]byte, error)

func (SeqIE[I, A]) String

func (s SeqIE[I, A]) String() string

func (*SeqIE[I, A]) UnmarshalJSON

func (s *SeqIE[I, A]) UnmarshalJSON(data []byte) error

type SetterFunc

type SetterFunc[S, T, B any] func(ctx context.Context, focus B, source S) (T, error)

Modification function for Lens type optics.

type TBiDir

type TBiDir interface {
	comparable
}

type TPure

type TPure interface {
	comparable
}

type TReadWrite

type TReadWrite interface {
	comparable
}

type TReturnOne

type TReturnOne interface {
	comparable
}

type UniDir

type UniDir []Void

Indicates this optic does not support reverseget

type ValueE

type ValueE[T any] struct {
	// contains filtered or unexported fields
}

Tuple of index and value. used by index optic operations.

func ValE

func ValE[T any](v T, err error) ValueE[T]

Constructor for ValueE

func (ValueE[T]) Error

func (iv ValueE[T]) Error() error

func (ValueE[T]) Get

func (v ValueE[T]) Get() (T, error)

Get returns the index and value as a tuple

func (ValueE[T]) String

func (iv ValueE[T]) String() string

func (ValueE[T]) Value

func (iv ValueE[T]) Value() T

type ValueI

type ValueI[I, T any] struct {
	// contains filtered or unexported fields
}

Tuple of index and value. used by index optic operations.

func ValI

func ValI[I, T any](i I, v T) ValueI[I, T]

Constructor for ValueI

func (ValueI[I, T]) Get

func (iv ValueI[I, T]) Get() (I, T)

Get returns the index and value as a tuple

func (ValueI[I, T]) Index

func (iv ValueI[I, T]) Index() I

func (ValueI[I, T]) String

func (iv ValueI[I, T]) String() string

func (ValueI[I, T]) Value

func (iv ValueI[I, T]) Value() T

type ValueIE

type ValueIE[I, T any] struct {
	// contains filtered or unexported fields
}

Tuple of index and value. used by [Range].

func ValIE

func ValIE[I, T any](i I, v T, err error) ValueIE[I, T]

Constructor for ValueIE

func (ValueIE[I, T]) Error

func (iv ValueIE[I, T]) Error() error

func (ValueIE[I, T]) Get

func (v ValueIE[I, T]) Get() (I, T, error)

Get returns the index and value as a tuple

func (ValueIE[I, T]) Index

func (iv ValueIE[I, T]) Index() I

func (ValueIE[I, T]) String

func (iv ValueIE[I, T]) String() string

func (ValueIE[I, T]) Value

func (iv ValueIE[I, T]) Value() T

type Void

type Void struct{}

Empty type as a placeholder in indexed optics when no index is available.

Directories

Path Synopsis
cmd
makecolops command
makelens command
vet command
examples
html-toupper command
json-extract command
pong command
recipes command
exp
cmd/makedblens command
examples/sort command
examples/tasks command
oio
Package expr contains the expression types for all built in optics, combinators and functions.
Package expr contains the expression types for all built in optics, combinators and functions.
internal
cmd/listfunc command
cmd/makecompose command
cmd/maketuple command
cmd/optic-fix command
playground command

Jump to

Keyboard shortcuts

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