otree

package
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: 10 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func BottomUp

func BottomUp[I, A any, RET, RW, DIR, ERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, ERR]

BottomUp is a [Traversal] that walks the tree in a bottom up order. During the traversal the child index is used to construct a path represented as a PathNode

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order C,B,D,A See: - BottomUpFiltered for a filtering version - TopDown for a top down version - BreadthFirst for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

optic := BottomUp(
	children,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[C B D A]

func BottomUpFiltered

func BottomUpFiltered[I, A, RET, RW, DIR, ERR, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

BottomUpFiltered is a [Traversal] that walks the tree in a bottom up order and filters out branches that don't match the predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is applied applied in top down order including the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order C,B,D,A See: - BottomUpFilteredI for an index aware predicate version. - BottomUp for a simpler non filtering version. - TopDownFiltered for a top down version - BreadthFirstFiltered for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose(
	OTree[int, string, Pure]().Value(),
	Ne("FilterMe"),
)

optic := BottomUpFiltered(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[C B D A]

func BottomUpFilteredI

func BottomUpFilteredI[I, A, RET, RW, DIR, ERR any, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred PredicateI[*PathNode[I], A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

BottomUpFilteredI is a [Traversal] that walks the tree in a bottom up order and filters out branches that don't match the index aware predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is applied applied in top down order including the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order C,B,D,A See: - BottomUpFiltered for a simpler non index aware predicate version. - BottomUp for a simpler non filtering version. - TopDownFilteredI for a top down version - BreadthFirstFilteredI for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose3(
	ValueIIndex[*PathNode[int], TreeNode[int, string, Pure]](),
	EqPath(Path(0, 1), EqT2[int]()),
	Not(),
)

optic := BottomUpFilteredI(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[C B D A]

func BreadthFirst

func BreadthFirst[I, A any, RET, RW, DIR, ERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR]) Optic[*PathNode[I], A, A, A, A, ReturnMany, ReadOnly, UniDir, ERR]

BreadthFirst is a [Traversal] that walks the tree in a breadth first order. During the traversal the child index is used to construct a path represented as a PathNode

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,D,C See: - BreadthFirstFiltered for a filtering version - TopDown for a top down version - BottomUp for a bottom up version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

optic := BreadthFirst(
	children,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B D C]

func BreadthFirstFiltered

func BreadthFirstFiltered[I, A, RET, RW, DIR, ERR, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]

BreadthFirstFiltered is a [Traversal] that walks the tree in a breadth first order and filters out branches that don't match the predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is applied applied in top down order including the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,D,C See: - BreadthFirstFiltered for a simpler non index aware predicate version. - BreadthFirst for a simpler non filtering version. - TopDownFiltered for a top down version - BottomUpFiltered for a bottom up version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose(
	OTree[int, string, Pure]().Value(),
	Ne("FilterMe"),
)

optic := BreadthFirstFiltered(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B D C]

func BreadthFirstFilteredI

func BreadthFirstFilteredI[I, A, RET, RW, DIR, ERR any, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred PredicateI[*PathNode[I], A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, ReadOnly, UniDir, CompositionTree[ERR, ERRP]]

BreadthFirstFilteredI is a [Traversal] that walks the tree in a breadth first order and filters out branches that don't match the index aware predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is applied applied in top down order including the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,D,C See: - BreadthFirstFiltered for a simpler non index aware predicate version. - BreadthFirst for a simpler non filtering version. - TopDownFilteredI for a top down version - BottomUpFilteredI for a bottom up version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose3(
	ValueIIndex[*PathNode[int], TreeNode[int, string, Pure]](),
	EqPath(Path(0, 1), EqT2[int]()),
	Not(),
)

optic := BreadthFirstFilteredI(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B D C]

func DiffTree

func DiffTree[I, J, A any, RET TReturnOne, RW any, DIR any, ERR any, DRET TReturnOne, ERRI TPure](right mo.Option[A], children Optic[J, A, A, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], threshold float64, distance Operation[lo.Tuple2[A, A], float64, DRET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRI], filterDiff DiffType, detectPosChange bool) Optic[Diff[*PathNode[I], A], mo.Option[A], mo.Option[A], mo.Option[A], mo.Option[A], ReturnMany, RW, UniDir, ERR]

func DiffTreeI

func DiffTreeI[I, J, A any, RET TReturnOne, RW, DIR, ERR any, DRET TReturnOne, ERRI TPure](right mo.Option[A], children Optic[J, A, A, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], threshold float64, distance Operation[lo.Tuple2[ValueI[*PathNode[I], A], ValueI[*PathNode[I], A]], float64, DRET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRI], filterDiff DiffType, detectPosChange bool) Optic[Diff[*PathNode[I], A], mo.Option[A], mo.Option[A], mo.Option[A], mo.Option[A], ReturnMany, RW, UniDir, ERR]

func DiffTreeT2

func DiffTreeT2[I, J, A any, RET TReturnOne, RW any, DIR any, ERR any, DRET TReturnOne, ERRI TPure](children Optic[J, A, A, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], threshold float64, distance Operation[lo.Tuple2[A, A], float64, DRET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRI], filterDiff DiffType, detectPosChange bool) Optic[Diff[*PathNode[I], A], lo.Tuple2[mo.Option[A], mo.Option[A]], lo.Tuple2[mo.Option[A], mo.Option[A]], mo.Option[A], mo.Option[A], ReturnMany, RW, UniDir, ERR]

func DiffTreeT2I

func DiffTreeT2I[I, J, A any, RET TReturnOne, RW, DIR, ERR any, DRET TReturnOne, ERRI TPure](children Optic[J, A, A, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], threshold float64, distance Operation[lo.Tuple2[ValueI[*PathNode[I], A], ValueI[*PathNode[I], A]], float64, DRET, ERR], ixMatch Predicate[lo.Tuple2[I, I], ERRI], filterDiff DiffType, detectPosChange bool) Optic[Diff[*PathNode[I], A], lo.Tuple2[mo.Option[A], mo.Option[A]], lo.Tuple2[mo.Option[A], mo.Option[A]], mo.Option[A], mo.Option[A], ReturnMany, RW, UniDir, ERR]

When a node is added only the added node is reported in the diff not all of it's children recursively.

func EqPath

func EqPath[I any, ERR TPure](right *PathNode[I], eq Predicate[lo.Tuple2[I, I], ERR]) Optic[Void, *PathNode[I], *PathNode[I], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

func EqPathT2

func EqPathT2[I any, ERR TPure](eq Predicate[lo.Tuple2[I, I], ERR]) Optic[Void, lo.Tuple2[*PathNode[I], *PathNode[I]], lo.Tuple2[*PathNode[I], *PathNode[I]], bool, bool, ReturnOne, ReadOnly, UniDir, Pure]

func EqTree

func EqTree[I comparable, A, ERR any, PERR TPure](right TreeNode[I, A, ERR], eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, TreeNode[I, A, ERR], TreeNode[I, A, ERR], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func EqTreeI

func EqTreeI[I, A, ERR any, PERR, IERR TPure](right TreeNode[I, A, ERR], ixMatch Predicate[lo.Tuple2[I, I], PERR], eq Predicate[lo.Tuple2[A, A], IERR]) Optic[optic.Void, TreeNode[I, A, ERR], TreeNode[I, A, ERR], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func EqTreeT2

func EqTreeT2[I comparable, A, ERR any, PERR TPure](eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[TreeNode[I, A, ERR], TreeNode[I, A, ERR]], lo.Tuple2[TreeNode[I, A, ERR], TreeNode[I, A, ERR]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func EqTreeT2I

func EqTreeT2I[I, A, ERR any, IERR, PERR TPure](ixMatch Predicate[lo.Tuple2[I, I], IERR], eq Predicate[lo.Tuple2[A, A], PERR]) Optic[Void, lo.Tuple2[TreeNode[I, A, ERR], TreeNode[I, A, ERR]], lo.Tuple2[TreeNode[I, A, ERR], TreeNode[I, A, ERR]], bool, bool, ReturnOne, ReadOnly, UniDir, ERR]

func MergeTree

func MergeTree[I, J, A, RET, SRET any, RW any, SRW ReadWrite, DIR, SDIR, ERR, SERR any](right A, children Optic[I, A, A, A, A, RET, RW, DIR, ERR], childrenCol Optic[J, A, A, Collection[I, A, SERR], Collection[I, A, SERR], SRET, SRW, SDIR, SERR]) Optic[Void, mo.Option[A], mo.Option[A], mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, SERR]]

func MergeTreeT2

func MergeTreeT2[I, J, A, RET, SRET any, RW any, SRW ReadWrite, DIR, SDIR, ERR, SERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], childrenCol Optic[J, A, A, Collection[I, A, SERR], Collection[I, A, SERR], SRET, SRW, SDIR, SERR]) Optic[Void, lo.Tuple2[mo.Option[A], mo.Option[A]], lo.Tuple2[mo.Option[A], mo.Option[A]], mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, SERR]]

func OTree

func OTree[I comparable, X, ERR any]() *lTree[X, I, optic.Void, TreeNode[I, X, ERR], TreeNode[I, X, ERR], optic.ReturnOne, optic.ReadWrite, optic.BiDir, ERR]

func OTreeFrom

func OTreeFrom[X any, I comparable, J any, S any, T any, RET any, RW any, DIR any, ERR any](l optic.Optic[J, S, T, TreeNode[I, X, ERR], TreeNode[I, X, ERR], RET, RW, DIR, ERR]) *lTree[X, I, J, S, T, RET, RW, DIR, ERR]

func OTreeFromI

func OTreeFromI[X any, I any, J any, S any, T any, RET any, RW any, DIR any, ERR any](l optic.Optic[J, S, T, TreeNode[I, X, ERR], TreeNode[I, X, ERR], RET, RW, DIR, ERR], ixmatch func(a, b I) bool) *lTree[X, I, J, S, T, RET, RW, DIR, ERR]

func OTreeI

func OTreeI[I any, X, ERR any](ixmatch func(a, b I) bool) *lTree[X, I, optic.Void, TreeNode[I, X, ERR], TreeNode[I, X, ERR], optic.ReturnOne, optic.ReadWrite, optic.BiDir, ERR]

func OTreeOpt

func OTreeOpt[I comparable, X, ERR any]() *loTree[X, I, optic.Void, mo.Option[TreeNode[I, X, ERR]], mo.Option[TreeNode[I, X, ERR]], optic.ReturnOne, optic.ReadWrite, optic.BiDir, ERR]

func OTreeOptFrom

func OTreeOptFrom[X any, I comparable, J any, S any, T any, RET any, RW any, DIR any, ERR any](l optic.Optic[J, S, T, mo.Option[TreeNode[I, X, ERR]], mo.Option[TreeNode[I, X, ERR]], RET, RW, DIR, ERR]) *loTree[X, I, J, S, T, RET, RW, DIR, ERR]

func OTreeOptFromI

func OTreeOptFromI[X any, I any, J any, S any, T any, RET any, RW any, DIR any, ERR any](l optic.Optic[J, S, T, mo.Option[TreeNode[I, X, ERR]], mo.Option[TreeNode[I, X, ERR]], RET, RW, DIR, ERR], ixmatch func(a, b I) bool) *loTree[X, I, J, S, T, RET, RW, DIR, ERR]

func OTreeOptI

func OTreeOptI[I any, X, ERR any](ixmatch func(a, b I) bool) *loTree[X, I, optic.Void, mo.Option[TreeNode[I, X, ERR]], mo.Option[TreeNode[I, X, ERR]], optic.ReturnOne, optic.ReadWrite, optic.BiDir, ERR]

func PathValue

func PathValue[I any]() Optic[Void, *PathNode[I], *PathNode[I], I, I, ReturnMany, ReadWrite, UniDir, Pure]

func ReIndexedTree

func ReIndexedTree[A any, I comparable, J comparable, L any, IRET TReturnOne, IRW any, IDIR any, ERR any](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, ERR]) Optic[Void, mo.Option[TreeNode[I, A, ERR]], mo.Option[TreeNode[I, A, ERR]], mo.Option[TreeNode[J, A, ERR]], mo.Option[TreeNode[J, A, ERR]], ReturnOne, IRW, IDIR, ERR]

func ReIndexedTreeP

func ReIndexedTreeP[A, B, I, J, L any, IRET TReturnOne, IRW any, IDIR any, ERR any](ixmap Optic[L, I, I, J, J, IRET, IRW, IDIR, ERR], ixmatch func(I, I) bool, ixmatchj func(J, J) bool) Optic[Void, mo.Option[TreeNode[I, A, ERR]], mo.Option[TreeNode[I, B, ERR]], mo.Option[TreeNode[J, A, ERR]], mo.Option[TreeNode[J, B, ERR]], ReturnOne, IRW, IDIR, ERR]

func ResolvePath

func ResolvePath[I, A, RET, RW, DIR, ERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], resolvePath *PathNode[I]) Optic[*PathNode[I], A, A, A, A, ReturnMany, ReadWrite, UniDir, ERR]

The ResolvePath combinator returns an optic that focuses the child element wth the given path.

Example
data := Tree(
	"alpha",
	ValCol(
		Tree("beta"),
		Tree("gamma",
			ValCol(Tree("delta")),
		),
	),
)

optic := ResolvePath(TraverseTreeChildren[int, string, Pure](), Path(1, 0))

var result TreeNode[int, string, Pure]
var ok bool
result, ok = MustGetFirst(optic, data)
fmt.Println(result, ok)

modifyResult := MustSet(optic, Tree("omega"), data)
fmt.Println(modifyResult)
Output:
{delta : Col[]} true
{alpha : Col[0:{beta : Col[]} 1:{gamma : Col[0:{omega : Col[]}]}]}

func Rewrite

func Rewrite[I, A, RET any, RW TReadWrite, DIR, ERR any, ORET TReturnOne, OERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], op Operation[A, mo.Option[A], ORET, OERR]) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, OERR]]

The Rewrite combinator focuses a rewritten version of the source tree.

The op parameter can be constructed using the RewriteOp family of constructors.

The tree is rewritten by applying the op to very node in the tree. If the op returns a some option then the value replaces the node in the tree. If the op returns none then the node remains unaltered. If any node was replaced then the whole process is run again until the op returns none for all nodes in the tree.

See:

  • Rewrite for a simpler non index non polymorphic version
  • RewriteI for an index aware version
Example
tree := Tree[any](
	"+",
	ValCol(
		Tree[any](
			"+",
			ValCol(
				Tree[any](1),
				Tree[any](2),
			),
		),
		Tree[any](3),
	),
)

opName := Compose(
	TreeValue[int, any, Pure](),
	DownCast[any, string](),
)

value := Compose(
	TreeValue[int, any, Pure](),
	DownCast[any, int](),
)

//Rewrite handler that evaluates the "+" function
rewriteHandler := RewriteOp(func(tree TreeNode[int, any, Pure]) (TreeNode[int, any, Pure], bool) {
	//If all the children are literal values we may be able to evaluate the expression
	childrenAllValues, _ := MustGetFirst(
		All(
			OTree[int, any, Pure]().Children().Traverse(),
			NotEmpty(value),
		),
		tree,
	)

	if childrenAllValues {

		funcName, _ := MustGetFirst(opName, tree)

		switch funcName {
		case "+":
			sumParams, _ := MustGetFirst(Reduce(Compose(OTree[int, any, Pure]().Children().Traverse(), value), Sum[int]()), tree)
			return Tree[any](sumParams), true
		}
	}

	return tree, false
})

newTree := MustGet(Rewrite(TraverseTreeChildren[int, any, Pure](), rewriteHandler), tree)

fmt.Println(newTree)

data := lo.T2("alpha", tree)

newTuple := MustModify(T2B[string, TreeNode[int, any, Pure]](), Rewrite(TraverseTreeChildren[int, any, Pure](), rewriteHandler), data)
fmt.Println(newTuple.A, newTuple.B)
Output:
{6 : Col[]}
alpha {6 : Col[]}

func RewriteI

func RewriteI[I, A, RET any, RW TReadWrite, DIR, ERR any, ORET TReturnOne, OERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], op OperationI[*PathNode[I], A, mo.Option[A], ORET, OERR]) Optic[Void, A, A, A, A, ReturnOne, ReadOnly, UniDir, CompositionTree[ERR, OERR]]

The RewriteI combinator focuses a rewritten version of the source tree.

The op parameter can be constructed using the RewriteOp family of constructors.

The tree is rewritten by applying the op to very node in the tree. If the op returns a some option then the value replaces the node in the tree. If the op returns none then the node remains unaltered. If any node was replaced then the whole process is run again until the op returns none for all nodes in the tree.

See:

  • Rewrite for a simpler non index non polymorphic version
  • RewriteI for an index aware version
Example
tree := Tree[any](
	"+",
	ValCol(
		Tree[any](
			"+",
			ValCol(
				Tree[any](1),
				Tree[any](2),
			),
		),
		Tree[any](3),
	),
)

opName := Compose(
	TreeValue[int, any, Pure](),
	DownCast[any, string](),
)

value := Compose(
	TreeValue[int, any, Pure](),
	DownCast[any, int](),
)

//Rewrite handler that evaluates the "+" function
rewriteHandler := RewriteOpI(func(path *PathNode[int], tree TreeNode[int, any, Pure]) (TreeNode[int, any, Pure], bool) {

	//Use index to prevent evaluation at the root of the tree
	if path == nil {
		return tree, false
	}

	//If all the children are literal values we may be able to evaluate the expression
	childrenAllValues, _ := MustGetFirst(All(OTree[int, any, Pure]().Children().Traverse(), NotEmpty(value)), tree)
	if childrenAllValues {

		funcName, _ := MustGetFirst(opName, tree)

		switch funcName {
		case "+":
			sumParams, _ := MustGetFirst(Reduce(Compose(OTree[int, any, Pure]().Children().Traverse(), value), Sum[int]()), tree)
			return Tree[any](sumParams), true
		}
	}

	return tree, false
})

newTree := MustGet(RewriteI(TraverseTreeChildren[int, any, Pure](), rewriteHandler), tree)

fmt.Println(newTree)

data := lo.T2("alpha", tree)

newTuple := MustModify(T2B[string, TreeNode[int, any, Pure]](), RewriteI(TraverseTreeChildren[int, any, Pure](), rewriteHandler), data)
fmt.Println(newTuple.A, newTuple.B)
Output:
{+ : Col[0:{3 : Col[]} 1:{3 : Col[]}]}
alpha {+ : Col[0:{3 : Col[]} 1:{3 : Col[]}]}

func RewriteOp

func RewriteOp[A any](rewriteHandler func(node A) (A, bool)) Optic[Void, A, A, mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, Pure]

RewriteOp constructs a rewrite operation.

See:

func RewriteOpE

func RewriteOpE[A any](rewriteHandler func(ctx context.Context, node A) (A, bool, error)) Optic[Void, A, A, mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, Err]

RewriteOpE constructs an error raising rewrite operation.

See:

func RewriteOpI

func RewriteOpI[I, A any](rewriteHandler func(index *PathNode[I], node A) (A, bool)) Optic[Void, ValueI[*PathNode[I], A], ValueI[*PathNode[I], A], mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, Pure]

RewriteOpI constructs an index aware rewrite operation.

See:

func RewriteOpIE

func RewriteOpIE[I, A any](rewriteHandler func(ctx context.Context, index *PathNode[I], node A) (A, bool, error)) Optic[Void, ValueI[*PathNode[I], A], ValueI[*PathNode[I], A], mo.Option[A], mo.Option[A], ReturnOne, ReadOnly, UniDir, Err]

RewriteOpIE constructs an index aware error raising rewrite operation.

See:

func TopDown

func TopDown[I, A any, RET, RW, DIR, ERR any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, ERR]

TopDown is a [Traversal] that walks the tree in a top down order. During the traversal the child index is used to construct a path represented as a PathNode

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,C,D See: - TopDownFiltered for a filtering version. - BottomUp for a bottom up version - BreadthFirst for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

optic := TopDown(
	children,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B C D]

func TopDownFiltered

func TopDownFiltered[I, A, RET, RW, DIR, ERR, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred Predicate[A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

TopDownFiltered is a [Traversal] that walks the tree in a top down order and filters out branches that don't match the predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is also applied to the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,C,D See: - TopDownFilteredI for an index aware predicate version. - TopDownMatch for a version that performs a match instead of filter.. - TopDown for a simpler non filtering version. - BottomUpFiltered for a bottom up version - BreadthFirstFiltered for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose(
	OTree[int, string, Pure]().Value(),
	Ne("FilterMe"),
)

optic := TopDownFiltered(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B C D]

func TopDownFilteredI

func TopDownFilteredI[I, A, RET, RW, DIR, ERR any, ERRP any](children Optic[I, A, A, A, A, RET, RW, DIR, ERR], pred PredicateI[*PathNode[I], A, ERRP]) Optic[*PathNode[I], A, A, A, A, ReturnMany, RW, UniDir, CompositionTree[ERR, ERRP]]

TopDownFilteredI is a [Traversal] that walks the tree in a top down order and filters out branches that don't match the index aware predicate. During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is also applied to the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,C,D See: - TopDownFiltered for a simpler non index aware predicate version. - TopDownMatchI for a version that performs a match instead of a filter - TopDown for a simpler non filtering version. - BottomUpFilteredI for a bottom up version - BreadthFirstFilteredI for a breadth first version

Example
tree := Tree(
	"A",
	ValCol(
		Tree(
			"B",
			ValCol(
				Tree("C"),
				Tree("FilterMe"),
			),
		),
		Tree("D"),
	),
)

children := TraverseTreeChildren[int, string, Pure]()

pred := Compose3(
	ValueIIndex[*PathNode[int], TreeNode[int, string, Pure]](),
	EqPath(Path(0, 1), EqT2[int]()),
	Not(),
)

optic := TopDownFilteredI(
	children,
	pred,
)

res := MustGet(
	SliceOf(
		Compose(
			optic,
			TreeValue[int, string, Pure](),
		),
		5,
	),
	tree,
)

fmt.Println(res)
Output:
[A B C D]

func TopDownMatch

func TopDownMatch[I, S, RET any, RW any, DIR any, ERR, MERR any](children Optic[I, S, S, S, S, RET, RW, DIR, ERR], matcher Predicate[S, MERR]) Optic[*PathNode[I], S, S, S, S, ReturnMany, RW, UniDir, ERR]

TopDownMatch is a [Traversal] that walks the tree in a top down order and focuses only branches that match the predicate. The top down walk ends at a matching branch.

During the traversal the child index is used to construct a path represented as a PathNode

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,C,D See: - TopDownMatchI for an index aware version - TopDownFilteredI for an version that filters instead of matches. - TopDown for a simpler non filtering version. - BottomUpFiltered for a bottom up version - BreadthFirstFiltered for a breadth first version

Example
data := Tree(
	":=",
	ValCol(
		Tree("x"),
		Tree("+",
			ValCol(
				Tree("1"),
				Tree("2"),
			),
		),
	),
)

//Match + nodes
matchAdd := Compose(
	OTree[int, string, Pure]().Value(),
	Eq("+"),
)

//TopDownMatch will find all matching sub trees
deepAdd := TopDownMatch(
	TraverseTreeChildren[int, string, Pure](),
	matchAdd,
)

var result []TreeNode[int, string, Pure] = MustGet(SliceOf(deepAdd, 10), data)
fmt.Println(result)

var modifyResult TreeNode[int, string, Pure]
modifyResult, err := Set(
	Compose(
		deepAdd,
		TreeValue[int, string, Pure](),
	),
	"-",
	data,
)
fmt.Println(modifyResult, err)
Output:
[{+ : Col[0:{1 : Col[]} 1:{2 : Col[]}]}]
{:= : Col[0:{x : Col[]} 1:{- : Col[0:{1 : Col[]} 1:{2 : Col[]}]}]} <nil>

func TopDownMatchI

func TopDownMatchI[I, S, RET any, RW any, DIR any, ERR, MERR any](children Optic[I, S, S, S, S, RET, RW, DIR, ERR], matcher PredicateI[*PathNode[I], S, MERR]) Optic[*PathNode[I], S, S, S, S, ReturnMany, RW, UniDir, ERR]

TopDownMatchI is a [Traversal] that walks the tree in a top down order and focuses only branches that match the index aware predicate. The top down walk ends at a matching branch.

During the traversal the child index is used to construct a path represented as a PathNode

Note: the predicate is also applied to the root node which may result in no tree elements being focused.

In a tree with this structure

+-A
  +-B
  | +-C
  +-D

The elements will be focused in the order A,B,C,D See: - TopDownMatch for a simpler non index aware predicate version. - TopDownFilteredI for a version that performs a filter instead of a match - TopDown for a simpler non filtering version. - BottomUpFilteredI for a bottom up version - BreadthFirstFilteredI for a breadth first version

func TraversePath

func TraversePath[I any]() Optic[int, *PathNode[I], *PathNode[I], I, I, ReturnMany, ReadOnly, UniDir, Pure]

func TraverseTreeChildren

func TraverseTreeChildren[I comparable, A, ERR any]() Optic[I, TreeNode[I, A, ERR], TreeNode[I, A, ERR], TreeNode[I, A, ERR], TreeNode[I, A, ERR], ReturnMany, ReadWrite, UniDir, ERR]

func TraverseTreeChildrenI

func TraverseTreeChildrenI[I, A, ERR any](ixmatch func(a, b I) bool) Optic[I, TreeNode[I, A, ERR], TreeNode[I, A, ERR], TreeNode[I, A, ERR], TreeNode[I, A, ERR], ReturnMany, ReadWrite, UniDir, ERR]

func TraverseTreeChildrenP

func TraverseTreeChildrenP[I, A, B any, ERR any, PERR TPure](ixMatch Predicate[lo.Tuple2[I, I], PERR]) Optic[*PathNode[I], TreeNode[I, A, ERR], TreeNode[I, B, ERR], A, B, ReturnMany, ReadWrite, UniDir, ERR]

func TreeChildren

func TreeChildren[I, A, ERR any]() Optic[Void, TreeNode[I, A, ERR], TreeNode[I, A, ERR], Collection[I, TreeNode[I, A, ERR], ERR], Collection[I, TreeNode[I, A, ERR], ERR], ReturnOne, ReadWrite, UniDir, Pure]

TreeChildren returns a [Lens] that focuses the direct children of a TreeNode

See:

  • [TreeChildrenP] for a polymorphic version.

func TreeValue

func TreeValue[I, A, ERR any]() Optic[Void, TreeNode[I, A, ERR], TreeNode[I, A, ERR], A, A, ReturnOne, ReadWrite, UniDir, Pure]

TreeChildren returns a [Lens] that focuses the direct children of a TreeNode

See:

  • [TreeChildrenP] for a polymorphic version.
Example
data := Tree[string](
	"Root",
	ValCol(
		Tree("Leaf 1"),
		Tree("Leaf 2"),
	),
)

var result string = MustGet(TreeValue[int, string, Pure](), data)
fmt.Println(result)

modifyResult := MustSet(TreeValue[int, string, Pure](), "New Root", data)

fmt.Println(modifyResult)
Output:
Root
{New Root : Col[0:{Leaf 1 : Col[]} 1:{Leaf 2 : Col[]}]}

func WithChildPath

func WithChildPath[I comparable, S, A any, RET any, RW, DIR, ERR any](o Optic[*PathNode[I], S, S, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR]) Optic[*PathNode[I], S, S, Collection[*PathNode[I], A, ERR], Collection[*PathNode[I], A, ERR], RET, RW, UniDir, ERR]

WithChildPath returns a Traversal that reindexes a [Collection] to a PathNode

See:

func WithChildPathI

func WithChildPathI[I, S, A any, RET any, RW, DIR, ERR any](o Optic[*PathNode[I], S, S, Collection[I, A, ERR], Collection[I, A, ERR], RET, RW, DIR, ERR], ixMatch func(a, b I) bool) Optic[*PathNode[I], S, S, Collection[*PathNode[I], A, ERR], Collection[*PathNode[I], A, ERR], RET, RW, UniDir, ERR]

WithChildPath returns a Traversal that reindexes a [Collection] to a PathNode

See:

  • WithChildPath for a simpler version that supports only comparable index types.

Types

type PathNode

type PathNode[I any] struct {
	// contains filtered or unexported fields
}

func Path

func Path[I any](indices ...I) *PathNode[I]

func (*PathNode[I]) Append

func (p *PathNode[I]) Append(i I) *PathNode[I]

func (*PathNode[I]) IxMatch

func (p *PathNode[I]) IxMatch(ixMatch func(indexA, indexB I) bool, other *PathNode[I]) bool

func (*PathNode[I]) Parent

func (p *PathNode[I]) Parent() *PathNode[I]

func (*PathNode[I]) Slice

func (p *PathNode[I]) Slice() []I

func (*PathNode[I]) String

func (p *PathNode[I]) String() string

func (*PathNode[I]) Value

func (p *PathNode[I]) Value() I

type TreeNode

type TreeNode[I, T, ERR any] struct {
	// contains filtered or unexported fields
}

TreeNode is a data structure representing a tree. A TreeNode has a value and a list of child trees.

See:

  • Tree for the constructor for this type.

func Tree

func Tree[T any](value T, children ...Collection[int, TreeNode[int, T, Pure], Pure]) TreeNode[int, T, Pure]

Tree is the constructor for TreeNode

See:

  • Tree for a version that supports arbitrary index types.
Example
data := Tree[string](
	"Root",
	ValCol(
		Tree("Leaf 1"),
		Tree("Leaf 2"),
	),
)

fmt.Println(data)
Output:
{Root : Col[0:{Leaf 1 : Col[]} 1:{Leaf 2 : Col[]}]}

func TreeE

func TreeE[T any](value T, children ...Collection[int, TreeNode[int, T, Err], Err]) TreeNode[int, T, Err]

func TreeI

func TreeI[I any, T any](value T, ixMatch func(a, b I) bool, children ...Collection[I, TreeNode[I, T, Pure], Pure]) TreeNode[I, T, Pure]

func TreeIE

func TreeIE[I any, T any, ERR any](value T, ixMatch func(a, b I) bool, children ...Collection[I, TreeNode[I, T, ERR], ERR]) TreeNode[I, T, ERR]

TreeIE is a constructor for TreeNode

See:

  • Tree for a simpler version that supports only comparable index types.

func (*TreeNode[I, T, ERR]) MarshalJSON

func (r *TreeNode[I, T, ERR]) MarshalJSON() ([]byte, error)

func (TreeNode[I, T, ERR]) String

func (r TreeNode[I, T, ERR]) String() string

func (*TreeNode[I, T, ERR]) UnmarshalJSON

func (r *TreeNode[I, T, ERR]) UnmarshalJSON(data []byte) error

Jump to

Keyboard shortcuts

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