Hyperon 0.2.1 Dispatch Patterns

Approved by Ursula Addison on 2026-05-14

Summary

Hyperon 0.2.1 does not reduce cond expressions: they are returned as symbolic data rather than evaluated to the matched branch's value. This page records the three dispatch patterns that do work in Hyperon 0.2.1 and the dependency-cascade hazard that follows when cond-producing functions are composed inside arithmetic or further dispatch. This guidance is load-bearing for MAGUS M2/M3/M4 integration on Hyperon 0.2.1 and for the MAGUS + HERMES integration for the AGI 2026 paper.

The cond gotcha

Expected behavior in some MeTTa dialects:

(cond
  ((== goal energy) 0.8)
  ((== goal exploration) 0.7)
  (otherwise 0.0))
; hoped-for result: 0.8

Actual behavior in Hyperon 0.2.1:

; returns the symbolic form, unreduced:
(cond (True 0.8) (False 0.7) (otherwise 0.0))

The conditions are treated as data. Because the outer form never reduces to a number, any composition like (* 5.0 (get-measurability goal)) is undefined rather than arithmetic.

Three dispatch patterns that do work

Pattern A — equality-based dispatch (preferred). Multiple = rules, one per branch, with a variable fallback:

(= (calculate-confidence energy) 0.8)
(= (calculate-confidence exploration) 0.7)
(= (calculate-confidence affinity) 0.5)
(= (calculate-confidence $_) 0.0)

Rationale: this is the idiomatic MeTTa pattern — the interpreter's unification already performs the dispatch, no conditional-form evaluation needed.

Pattern B — nested if. When you need a single definition site (for example, inline debugging) and the branches share structure:

(= (calculate-confidence $goal)
   (if (== $goal energy) 0.8
     (if (== $goal exploration) 0.7
       (if (== $goal affinity) 0.5 0.0))))

Pattern C — case. Works in Hyperon 0.2.1 and reads more cleanly for three or more branches:

(= (calculate-confidence $goal)
   (case $goal
     ((energy 0.8)
      (exploration 0.7)
      (affinity 0.5)
      ($_ 0.0))))

Dependency-cascade warning

If a function returns an unreduced cond, callers that embed it in arithmetic or further dispatch silently inherit the non-reduction. Example from MAGUS M3 metagoals integration:

; Milestone_3/core/metagoals.metta
(* (/ $count $duration) (get-measurability (goal-name $goal)))

When get-measurability was defined via cond, the inner expression evaluated to a symbolic form, so the outer multiplication never produced a number. The failure is silent: no runtime error, just downstream code receiving non-numeric inputs. Before integrating any helper into arithmetic, confirm it reduces to a concrete value with a direct invocation:

!(get-measurability energy)
; must return [0.72], not [(cond (True 0.72) ...)]

Process notes

  • Execute before documenting. During M2/M3 the failure mode was claiming "tests pass" from code structure alone without running them. Always invoke helpers in the REPL and verify the concrete value before composing them.
  • Verify language features against the target runtime. Not all MeTTa dialects implement the same surface. If a construct appears in other dialects' examples, confirm it reduces in Hyperon 0.2.1 before building on it.
  • Incremental validation. Test each dispatch helper the moment it is written, not at integration time, so failures surface while the fix is cheap.

Scope and provenance

Distilled from the MAGUS Milestone 2/3 post-mortem (October 2025) to port only the findings that remain load-bearing on Hyperon 0.2.1. Applies to the MAGUS implementation at github.com/Magi-AGI/MAGUS and to the MAGUS + HERMES integration for the AGI 2026 paper (github.com/Magi-AGI/HERMES). Broader process retrospective lives on the internal Magi Archive.