package
0.0.0-20231115175402-ada8b72c9a54
Repository: https://github.com/npillmayer/fp.git
Documentation: pkg.go.dev

# README

Concurrent Tree Operations

There are many tree implementations around. This one supports trees of a fairly simple structure. However, this package makes heavy use of concurrency for all kinds of tree operations. Tree traversal and modification are often performed asynchronously by creating pipelines of concurrent filters. This is done transparently for the client, only reflected by getting a promise as a return type.

For small trees the overhead of concurrency may hurt, from a performance point of view. This package is meant for fairly large DOMs with potentially complex styling information. However, it is generalized enough to be useful in other scenarios as well. And to be honest: I wrote it because concurrency in Go is kind of fun!

DSL

We support a set of search & filter functions on tree nodes. Clients will chain these to perform tasks on nodes (see examples below). You may think of the set of operations to form a small Domain Specific Language (DSL). This is similar in concept to JQuery, but of course with a much smaller set of functions.

Navigation functions:

TopDown(action)              // operate on all nodes, starting at the top
Parent()                     // find parent for all selected nodes
AncestorWith(predicate)      // find ancestor with a given predicate
DescendentsWith(predicate)   // find descendets with a given predicate
AllDescendents()             // find all descendents of selected nodes

Filter functions:

AttributeIs(key, value)      // filter for nodes with a given attribute value
SetAttribute(key, value)     // set an attribute value for nodes
Filter(userfunc)             // apply a user-provided filter function

More operations will follow as I get experience from using the tree in more real life contexts.

Tree Walker

Operations on trees start with creating a Walker for the tree. A typical usage of a Walker looks like this ("FindNodesAndDoSomething()" is a placeholder for a sequence of DSL function calls):

w := NewWalker(rootnode)
futureResult := w.FindNodesAndDoSomething(...).Promise()
nodes, err := futureResult()

Clients always have to call Promise() as the final link of the DSL expression chain, even if they do not expect the expression to return a non-empty set of nodes.

# Functions

appendFilter appends a filter to a pipeline, i.e.
CalcRank is an action for bottom-up processing.
NewNode creates a new tree node with a given payload.
NewWalker creates a Walker for the initial node of a (sub-)tree.
NodeIsLeaf is a predicate to match leafs of a tree.
Whatever is a predicate to match anything (see type Predicate).

# Variables

ErrEmptyTree is thrown if a Walker is called with an empty tree.
ErrInvalidFilter is thrown if a pipeline filter step is defunct.
ErrNoMoreFiltersAccepted is thrown if a client already called Promise(), but tried to re-use a walker with another filter.

# Structs

Node is the base type our tree is built of.
Walker holds information for operating on trees: finding nodes and doing work on them.

# Type aliases

Action is a function type to operate on tree nodes.
Predicate is a function type to match against nodes of a tree.