For significantly more detail, discussion, examples and illustrations, read Reflective Programs in Tree Calculus by Barry Jay.
Definition: Tree calculus expressions
have abstract syntax . A note on notation: Parentheses are used to clarify structure, e.g. to distinguish
from . To reduce the number of parentheses required in practice, we assume that the binary operator is left associative. For instance, means . This convention is standard in combinatory logic and was already used by Moses Schönfinkel. Expressions are reduced according to the following small-step semantics:
Note: We call these particular reduction rules triage calculus. Johannes Bader suggested these as an alternative to the original rules, see Barry’s blog post for more context.
Conventions:
- We call irreducible expressions values or programs.
- We can think of expressions as unlabeled trees, generated by interpreting every subexpression
as a node with as child trees.- We call expression
leaf. - We call expressions
stem of . - We call expressions
fork of and .
- We call expression
Tip: Check out Timur Latypoff’s visualization of these rules and conventions. Thanks Timur!
Consequences:
- Values are binary trees, i.e. only consist of leafs, stems and forks. As long as there is a subexpression
, one of the reduction rules apply. - Tree Calculus is Turing complete: Reduction rules
and are analogous to K and S operators of combinatory logic. - Tree Calculus is intensional: Rules
allow reflecting on values by distinguishing leafs, stems and forks. - Tree Calculus is confluent: The five reduction rules are non-overlapping and only allow observing values, not reducible expressions.
Example reduction: Negating booleans
If we define
and
The tree representation of