Nested nodes#
The product of chain() or node() and other builders is called node for a reason, and the reason is that those
objects (components) can be composed to create other nodes.
node(function)is the simplest node (leaf or edge node), it runs the function inside a context and reports in case of errorchain(function1, function2, function3)is a chain of nodesnode(function1),node(function2)andnode(function3), it calls the first node and then passes its result to the next if itโs successful, but the โchainโ is also a node and can be composed with other nodes to produce another one
>>> from funchain import node
>>> double = node(lambda x: x*2, 'double')
>>> increment = node(lambda x: x+1, 'increment')
>>> increment_double = increment | double # or chain(increment, double)
>>> increment_double(5)
12
>>> # Reusing `increment_double` in another chain
>>> idd = increment_double | double
>>> idd(5)
24
>>> iddi = idd | increment
>>> iddi(5)
25
chain({'a': function1, 'b': function2})produces a model of nodes, the same aschain([function1, function2])does, those models pass their input to each of their branches and return the result asdictorlist. Models are also nodes, so they can be composed with more nodes or contain complex branches themselves;
>>> model = chain([increment, double])
>>> model(5)
[6, 10]
>>> agg = model | sum
>>> agg(5)
16
>>> model_double = model * double # doubles each item
>>> model_double(5)
[12, 20]
>>> another_model = chain({
... 'identical': (), # () means here an empty chain
... 'agg': ([increment, double], sum), # means a chain with two nodes a model and a function
... 'model_double': model_double # contains a pre-built model (node in general)
... })
{'identical': 5, 'agg': 16, 'model_double': [12, 20]}
The purpose is to demonstrate that all type of nodes share a common interface and can be nested as much as we need to achieve the required result.