Indexed optics focus an index value in addition to the value. This typically occurs when traversing a collection.
| |
Here we have used SeqIOf which is the index aware version of SeqOf. SeqIOf focuses an iter.Seq2 of the focused index and value.
The result is this sequence of values being printed.
alpha 1
beta 2
delta 4
gamma 3
Traversing a map in go optics always iterates the value in a consistent order. The sorting is performed by sorting by the index values.
There is only 1 active index at any time. Compose by default maintains the right optic“s index. This can cause the index to be lost.
| |
Mul(10) doesn’t have an index and this causes the TraverseMap’s index to be lost. The result is this sequence of values being printed.
{} 10
{} 20
{} 40
{} 30
In go-optics an empty struct called Void is used to represent the lack of an index.
There are 3 built in variants of Compose that can retain either the left or both indices.
ComposeLeftretains the left index.ComposeBothretains both indices wrapped in alo.Tuple2ComposeIuses a user providedIxMapperto map the index.
Compose Left #
ComposeLeft is a drop in replacement for Compose that retains the left instead of right index.
| |
This example now focuses the string index from the map instead of the Void index from the Mul(10) operation. The example prints the following values.
alpha 10
beta 20
delta 40
gamma 30
The index focused by ComposeLeft is compatible with the Index combinator which focuses a value at a given index.
| |
This prints the following values.
| |
ComposedLeft provides Index with an optimised optic that is still able to perform a data["beta"} lookup into the map.
Compose Both #
ComposeBoth is also a drop in replacement for Compose that retains both indices as a lo.Tuple2
| |
{0 alpha} 1
{0 beta} 2
{1 delta} 4
{1 gamma} 3
ComposeBoth also provides an optimized Index implementation. We simply pass the 2 index values as a lo.Tuple2
| |
This example returns the “gamma” value from the second slice. The Index was able to perform both the slice index and map lookup data[1]["gamma"]
| |
ComposeI #
ComposeI enables custom mapping of the index. The mapping is performed by an IxMap optic. By using the IxMapIso constructor the composed optic is able to provide an optimized Index implementation as it is able to recover the original index values by performing a ReverseGet on the IxMap
| |
This example is equivalent to a ComposeBoth
{0 alpha} 1
{0 beta} 2
{1 delta} 4
{1 gamma} 3
Reindexing #
It’s sometimes necessary to modify the index of an optic for example when building a map. For this purposes the reindexing combinators can be used.
| |
This example uses the ReIndexed combinator to modify the int index of a slice traversal and converts it into a string and builds a map from the result. The EqT2 parameter is an IxMatch optic. It is used to perform equality checks on the new index during Index lookups using the new index. After reindexing the Index lookup is performed by filtering on the index using the IxMatch
There are several other reindexing combinators.
| Combinator | Purpose |
|---|---|
Indexed | replaces the index with an integer counter |
SelfIndex | uses the focused element as the index |
ReIndexed | enables an arbitrary transformation if the index |
By combining the SelfIndex and ReIndexed combinators an arbitrary property of the focus can be used as the index.
| |
This example prints
map[Erika Mustermann:{Erika Mustermann 37} Max Mustermann:{Max Mustermann 42}] <nil>
By using the reindexed combinators arbitrary transformations can be applied to the index of an optic.