|
1 |
| -// This package provides functional utilities for traversing and transforming |
2 |
| -// IPLD nodes. |
3 |
| -// |
4 |
| -// The traversal.Path type provides a description of how to perform |
5 |
| -// several steps across a Node tree. These are dual purpose: |
6 |
| -// Paths can be used as instructions to do some traversal, and |
7 |
| -// Paths are accumulated during traversals as a log of progress. |
8 |
| -// |
9 |
| -// "Focus" functions provide syntactic sugar for using ipld.Path to jump |
10 |
| -// to a Node deep in a tree of other Nodes. |
11 |
| -// |
12 |
| -// "FocusedTransform" functions can do the same such deep jumps, and support |
13 |
| -// mutation as well! |
14 |
| -// (Of course, since ipld.Node is an immutable interface, more precisely |
15 |
| -// speaking, "transformations" are implemented rebuilding trees of nodes to |
16 |
| -// emulate mutation in a copy-on-write way.) |
17 |
| -// |
18 |
| -// "Walk" functions perform a walk of a Node graph, and apply visitor |
19 |
| -// functions multiple Nodes. The more advanced Walk functions can be guided |
20 |
| -// by Selectors, which provide a declarative mechanism for guiding the |
21 |
| -// traversal and filtering which Nodes are of interest. |
22 |
| -// (See the selector sub-package for more detail.) |
23 |
| -// |
24 |
| -// "WalkTransforming" is similar to Traverse, but with support for mutations. |
25 |
| -// Like "FocusTransform", "WalkTransforming" operates in a copy-on-write way. |
26 |
| -// |
27 |
| -// All of these functions -- the "Focus*" and "Walk*" family alike -- |
28 |
| -// work via callbacks: they do the traversal, and call a user-provided function |
29 |
| -// with a handle to the reached Node. Further "Focus" and "Walk" can be used |
30 |
| -// recursively within this callback. |
31 |
| -// |
32 |
| -// All of these functions -- the "Focus*" and "Walk*" family alike -- |
33 |
| -// include support for automatic resolution and loading of new Node trees |
34 |
| -// whenever IPLD Links are encountered. This can be configured freely |
35 |
| -// by providing LinkLoader interfaces to the traversal.Config. |
36 |
| -// |
37 |
| -// Some notes on the limits of usage: |
38 |
| -// |
39 |
| -// The "*Transform" family of methods is most appropriate for patterns of usage |
40 |
| -// which resemble point mutations. |
41 |
| -// More general transformations -- zygohylohistomorphisms, etc -- will be best |
42 |
| -// implemented by composing the read-only systems (e.g. Focus, Traverse) and |
43 |
| -// handling the accumulation in the visitor functions. |
44 |
| -// |
45 |
| -// (Why? The "point mutation" use-case gets core library support because |
| 1 | +// Package traversal provides functional utilities for traversing and |
| 2 | +// transforming IPLD graphs. |
| 3 | +// |
| 4 | +// Two primary types of traversal are implemented in this package: "Focus" and |
| 5 | +// "Walk". Both types have a "Transforming" variant, which supports mutation |
| 6 | +// through emulated copy-on-write tree rebuilding. |
| 7 | +// |
| 8 | +// Traversal operations use the Progress type for configuration and state |
| 9 | +// tracking. Helper functions such as Focus and Walk exist to avoid manual setup |
| 10 | +// of a Progress struct, but they cannot cross link boundaries without a |
| 11 | +// LinkSystem, which needs to be configured on the Progress struct. |
| 12 | +// |
| 13 | +// A typical traversal operation involves creating a Progress struct, setting up |
| 14 | +// the LinkSystem, and calling one of the Focus or Walk functions on the |
| 15 | +// Progress object. Various other configuration options are available when |
| 16 | +// traversing this way. |
| 17 | +// |
| 18 | +// # Focus |
| 19 | +// |
| 20 | +// "Focus" and "Get" functions provide syntactic sugar for using ipld.Path to |
| 21 | +// access Nodes deep within a graph. |
| 22 | +// |
| 23 | +// "FocusedTransform" resembles "Focus" but supports user-defined mutation using |
| 24 | +// its TransformFn. |
| 25 | +// |
| 26 | +// # Walk |
| 27 | +// |
| 28 | +// "Walk" functions perform a recursive walk of a Node graph, applying visitor |
| 29 | +// functions to matched parts of the graph. |
| 30 | +// |
| 31 | +// The selector sub-package offers a declarative mechanism for guiding |
| 32 | +// traversals and filtering relevant Nodes. |
| 33 | +// (Refer to the selector sub-package for more details.) |
| 34 | +// |
| 35 | +// "WalkLocal" is a special case of Walk that doesn't require a selector. It |
| 36 | +// walks a local graph, not crossing link boundaries, and calls its VisitFn for |
| 37 | +// each encountered Node. |
| 38 | +// |
| 39 | +// "WalkMatching" traverses according to a selector, calling the VisitFn for |
| 40 | +// each match based on the selector's matching rules. |
| 41 | +// |
| 42 | +// "WalkAdv" performs the same traversal as WalkMatching, but calls its |
| 43 | +// AdvVisitFn on every Node, regardless of whether it matches the selector. |
| 44 | +// |
| 45 | +// "WalkTransforming" resembles "WalkMatching" but supports user-defined |
| 46 | +// mutation using its TransformFn. |
| 47 | +// |
| 48 | +// # Usage Notes |
| 49 | +// |
| 50 | +// These functions work via callbacks, performing traversal and calling a |
| 51 | +// user-provided function with a handle to the reached Node(s). Further "Focus" |
| 52 | +// and "Walk" operations can be performed recursively within this callback if |
| 53 | +// desired. |
| 54 | +// |
| 55 | +// All traversal functions operate on a Progress object, except "WalkLocal", |
| 56 | +// which can be configured with a LinkSystem for automatic resolution and |
| 57 | +// loading of new Node trees when IPLD Links are encountered. |
| 58 | +// |
| 59 | +// The "*Transform" methods are best suited for point-mutation patterns. For |
| 60 | +// more general transformations, use the read-only systems (e.g., Focus, |
| 61 | +// Traverse) and handle accumulation in the visitor functions. |
| 62 | +// |
| 63 | +// A common use case for walking traversal is running a selector over a graph |
| 64 | +// and noting all the blocks it uses. This is achieved by configuring a |
| 65 | +// LinkSystem that can handle and observe block loads. Be aware that a selector |
| 66 | +// might visit the same block multiple times during a traversal, as IPLD graphs |
| 67 | +// often form "diamond patterns" with the same block referenced from multiple |
| 68 | +// locations. |
| 69 | +// |
| 70 | +// The LinkVisitOnlyOnce option can be used to avoid duplicate loads, but it |
| 71 | +// must be used carefully with non-trivial selectors, where repeat visits of |
| 72 | +// the same block may be essential for traversal or visit callbacks. |
| 73 | +// |
| 74 | +// A Budget can be set at the beginning of a traversal to limit the number of |
| 75 | +// Nodes and/or Links encountered before failing the traversal (with the |
| 76 | +// ErrBudgetExceeded error). |
| 77 | +// |
| 78 | +// The "Preloader" option provides a way to parallelize block loading in |
| 79 | +// environments where block loading is a high-latency operation (such as |
| 80 | +// fetching over the network). |
| 81 | +// The traversal operation itself is not parallel and will proceed strictly |
| 82 | +// according to path or selector order. However, a Preloader can be used to load |
| 83 | +// blocks asynchronously, and prepare the LinkSystem that the traversal is using |
| 84 | +// with already-loaded blocks. |
| 85 | +// |
| 86 | +// A Preloader and a Budget option can be used on the same traversal, BUT the |
| 87 | +// Preloader may not receive the same links that the traversal wants to load |
| 88 | +// from the LinkSystem. Use with care. See notes below. |
| 89 | +package traversal |
| 90 | + |
| 91 | +// Why only "point-mutation"? This use-case gets core library support because |
46 | 92 | // it's both high utility and highly clear how to implement it.
|
47 | 93 | // More advanced transformations are nontrivial to provide generalized support
|
48 | 94 | // for, for three reasons: efficiency is hard; not all existing research into
|
|
53 | 99 | // Therefore, attempts at generalization are not included here; handling these
|
54 | 100 | // issues in concrete cases is easy, so we call it an application logic concern.
|
55 | 101 | // However, exploring categorical recursion schemes as a library is encouraged!)
|
56 |
| -package traversal |
|
0 commit comments