Introduction to Evaluation
← MeTTa Tutorial · Lesson 1 of 5
Introduction to Evaluation in MeTTa. How MeTTa represents programs as data, and how it reduces (evaluates) them. By the end you can define functions, use recursion and conditionals, and see how a single expression can return more than one result.
Main concepts
Everything in MeTTa is an atom. There are four kinds:
- Symbols — bare names like
Hello,cat, or+. - Variables — names beginning with
$, like$x, standing for “anything”. - Grounded atoms — values with built-in behaviour, like the number
42or the operation+. - Expressions — atoms combined in parentheses, like
(+ 2 3)or(parent Tom Bob). Expressions nest freely.
A MeTTa program is just a collection of atoms. Crucially, code and data share the same shape: (+ 2 3) is both an expression you can evaluate and a piece of data you can match against. That is what lets MeTTa inspect and rewrite its own programs.
You add a reduction rule with =, and you evaluate an expression by prefixing it with !. Results print as a list:
; a rule: (greet) reduces to Hello
(= (greet) Hello)
; evaluate it
!(greet) ; [Hello]
Basic evaluation
Grounded operations such as arithmetic work out of the box, and nested expressions reduce from the inside out:
!(+ 2 3) ; [5]
!(* (+ 1 2) 4) ; [12] inner (+ 1 2) reduces to 3 first
Define your own functions as equations. The left-hand side is a pattern with variables; the right-hand side is what it reduces to:
(= (double $x) (* 2 $x))
!(double 21) ; [42]
Evaluating (double 21) matches the rule, binds $x to 21, and reduces the right-hand side.
Recursion and control
Use if for conditionals — it takes a Boolean, a then-branch, and an else-branch:
(= (abs $x) (if (< $x 0) (* -1 $x) $x))
!(abs -7) ; [7]
!(abs 4) ; [4]
Functions can call themselves. Writing the recursion with if — rather than two overlapping rules — keeps a single, unambiguous definition and a clean base case:
(= (fact $n)
(if (== $n 0)
1
(* $n (fact (- $n 1)))))
!(fact 5) ; [120]
Free variables and nondeterminism
A variable left unbound is a free variable — it stands for any atom. And unlike most languages, a MeTTa expression can reduce to more than one result: if several rules match, you get them all.
(= (coin) heads)
(= (coin) tails)
!(coin) ; [heads, tails]
You can also produce several results directly with superpose, and gather them back into a single tuple with collapse:
!(superpose (1 2 3)) ; [1, 2, 3]
!(collapse (superpose (1 2 3))) ; [(1 2 3)]
This nondeterminism is central to MeTTa: one query can explore many possibilities at once — the foundation for the pattern matching and search you will meet next.
Next
Lesson 2 — Patterns of Knowledge — querying space content, functions and unification, and nested queries. Or try these examples in the metta-lang.dev Playground, or open the MeTTa Deep Dive.