Edited transcript of a conversation between Jacques and Hans
We want to build functions and we want to evaluate functions that we have built before. We can have various systems to build functions and various systems to evaluate functions. It now happens to be the case that sometimes one system is capable of building and evaluating functions. However, these should still be considered to be separate tasks.
When evaluating a function we typically have to look at the function and the context to determine the best way to evaluate it. The system used for evaluation might be the same system that built the function, but it might be a separate system on the CPU, or it might run the function on the GPU. Theoretically, it could even make sense that an individual node, in order to evaluate a geometry field, creates a new geometry-nodes-evaluator during its execution. Then we would have nested geometry-nodes-evaluators.
The geometry nodes evaluator and multi-function procedure evaluator are both essentially just moving generic data around and call functions with that data. The evaluator is responsible for the overall geometry nodes evaluation, building up the callbacks that can then be used by individual nodes. We also want to be able to evaluate fields separate from the evaluator (e.g. for the viewer maybe). When the geometry nodes evaluator executes the function nodes, it should just create a new field that also references the input fields. It does not actually evaluate the fields, that is done by the node that uses the field. In the prototype the evaluator also does not evaluate the fields (unless it is constant, which is not important right now).
Basically, you build up some kind of tree data structure when the nodes are evaluated. Then, when the field is evaluated, this tree is converted into a multi-function procedure, and then you evaluate this procedure. The multi-function field just references a bunch of other fields.
One benefit of building up the separate field tree structure and evaluating it as a procedure is that the procedure system can look at all of the nodes at once and make optimizations that the evaluator, which works at the node level, wouldn't be able to do. Also the evaluator can't really evaluate the fields because it has no idea about the context the fields are evaluated in. We could keep track of that context, but it would add a lot of complexity and it wouldn't really fit.