sicp.io
4.4.6 · Implementing the query system

Unification joins assertions and renamed rules under one frame protocol.

Implement bidirectional variable unification, rule-variable renaming, assertion and rule search, negation-as-failure, and an explicit rule-depth budget.

Guiding question

What additional machinery lets a query match not only stored facts but also conclusions derived from reusable rules?

  • Unify variables appearing on either side of a comparison
  • Follow an existing variable binding before extending a frame
  • Rename every rule variable for each application
  • Apply a rule by unifying its conclusion and evaluating its body
  • Combine and, or, and finite negation-as-failure over frame lists
  • Bound recursive rule application with an explicit remaining depth

unify-match generalizes simple assertion matching. Either input may be a variable, and an existing binding may lead to another variable or structure before the comparison finishes. Before every rule application, rename-rule replaces each logical variable with a fresh key carrying the current rule-application id. This prevents a rule’s private intermediate names from colliding with query variables or another application of the same rule.

simple-query combines direct assertion matches with rule results. A rule result unifies the query pattern with the renamed conclusion, then sends the resulting frame through qeval on the rule body. and pipelines frames, or appends alternatives, and not keeps a frame only when its subquery has no result under that frame. The explicit depth is the exact finite resource boundary for rule expansion.

SICP code6,009 of 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Execution trace0 / 0 events
    Programs run in the browser with their result and execution trace.
    Expected result

    The engine returns (((grandchild carol) (grandchild dave)) (dave) 2).

    Trace focus

    Follow the query pattern into direct assertion matching and then into each renamed rule conclusion. Inspect the fresh variable keys before the grandparent body enters conjoin. For the negated parent query, show why carol is rejected and dave is retained. Confirm that the two or branches start from the same empty input frame.

    Try it yourself

    Change the program and compare the result.

    Add an ancestor rule with a direct parent clause and a recursive clause. Run it with depth 4 and depth 1, report the answers separately, and explain how the work budget determines the result frontier.

    Show hint

    Use two rules with the same ancestor conclusion. The recursive body should introduce one fresh intermediate variable and call ancestor with the remaining depth budget.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%