MeTTa has an `m` in it - trueagi-io/metta-wam GitHub Wiki

The m function in MeTTa is the core logic execution engine, handling goal evaluation, rule expansion, backward chaining, backtracking, and unification. It operates in a default context (&self), which can be overridden (ctx &them ...) inside or outside of m.

Key Features of m

  • Expands functions and rules before execution.
  • Backtracks and retries on failure.
  • Unifies facts and rules like Prolog.
  • Executes in a specific logical context (ctx &self or ctx &them).
  • Supports logical operators (or, not, naf, call, eval, ignore, limit, count-of, unique, at-least).
  • Implicit and behavior—all statements inside m must succeed.
  • Ensures all variable bindings are returned if True is placed at the end.

How m Works

When m is executed, it follows these steps:
1️⃣ Expands function calls into their definitions.
2️⃣ Expands rule heads into their bodies.
3️⃣ Performs fact queries against the knowledge base.
4️⃣ Executes in the default &self context unless overridden.
5️⃣ Backtracks and retries on failure.
6️⃣ Returns variable bindings if successful, or the last computed value if applicable.


Implicit and Behavior

Unlike Prolog, and is implicit in m—all statements inside m must succeed for execution to continue.

Example: Implicit and in m

(m
    (rdf! $Gene ex:gene_name "BRCA2")  ;; Must succeed
    (rdf! $Gene ex:transcribed_to $Transcript)  ;; Must succeed
    (rdf! $Transcript ex:translates_to $Protein)  ;; Must succeed
)
  • If any statement fails, m backtracks and retries.
  • Unlike Prolog, you don’t need explicit and—each statement must succeed.

The Special Role of True at the End of m

Placing True at the end ensures that the final return value is always the full set of variable bindings.

  • If the last statement normally returns a value, that value is discarded and all variable bindings are returned instead.
  • If there is no True at the end, m returns the value of the last executed statement instead.

Example Without True

(m
    (rdf! "BRCA2" ex:gene_length $Length)
)

Returns:

1005

(The direct value of $Length is returned.)

Example With True

(m
    (rdf! "BRCA2" ex:gene_length $Length)
    True
)

Returns:

(($Length "1005"))

(The variable binding is returned instead of just the value.)


Logical Operators in m

While and is implicit, m supports explicit logical operators:

  • or – At least one condition must be true.
  • not – Logical negation (fails if the condition is true).
  • naf – Negation as failure (succeeds if the query fails).
  • call – Forces head/fact unification.
  • eval – Forces function call evaluation.
  • ignore – Allows failure without stopping execution.
  • limit – Cuts execution after a set number of answers.
  • count-of – Returns the number of matching solutions.
  • unique – Ensures unique results by filtering duplicates.
  • at-least – Ensures at least n answers are found.

Advanced Query Controls

1️⃣ Limiting Execution (limit)

Use limit to restrict the number of results.

Example: Limit to 2 Results

(m
    (limit 2
        (rdf! "BRCA2" ex:transcribed_to $Transcript)
        (rdf! $Transcript ex:translates_to $Protein)
    )
)

Stops after 2 results, even if more exist.


2️⃣ Counting Results (count-of)

Use count-of to return the number of solutions.

Example: Count All Transcripts

(m
    (count-of
        (rdf! "BRCA2" ex:transcribed_to $Transcript)
    )
)

Returns: 3 (if three transcripts exist).


3️⃣ Ensuring Unique Results (unique)

Use unique to eliminate duplicate solutions.

Example: Ensure Unique Pathways

(m
    (unique
        (rdf! "BRCA2" ex:genes_pathways $Pathway)
    )
)

Ensures each pathway is listed only once.


4️⃣ Ensuring a Minimum Number of Results (at-least)

Use at-least to force m to find a minimum number of answers.

Example: Require at Least 2 Solutions

(m
    (at-least 2
        (rdf! "BRCA2" ex:transcribed_to $Transcript)
    )
)

Fails if fewer than 2 transcripts are found.


Context Handling (ctx)

By default, m runs in context &self, but can execute in any context:

(ctx &them (m (rdf! $Gene ex:gene_name "BRCA2")))
  • This allows execution in a different logical space (&them).
  • ctx can be inside or outside of m.

Examples of Query Execution

1️⃣ Retrieving a Query by Name & Type

!(m (test-query brca2 sparql $query))
!(m (test-query igf2 prolog-rdf $query))
!(m (test-query brca2 metta-rdf $query))

2️⃣ Running a Local RDF Query

!(m (test-query brca2 prolog-rdf $query) (call-p $query))

3️⃣ Executing a SPARQL Query

!(m (test-query brca2 sparql $query) (call-fn sparql-internal ($query $Results)))

4️⃣ Evaluating a MeTTa Query

!(m (test-query brca2 metta-rdf $metta-code) (eval $metta-code))
!(m (test-query igf2 metta-rdf $metta-code) (eval $metta-code))

Conclusion

The m function is the core logic execution engine in MeTTa, enabling:

  • Implicit and for execution chaining.
  • Backward chaining for inference.
  • Backtracking & retrying when queries fail.
  • Execution in different contexts (ctx).
  • Logical operators (or, not, naf, call, eval, ignore, limit, count-of, unique, at-least).
  • Returning variable bindings when True is specified at the end.