# Python Premise Syntax

## Python_premise

    python_premise ::= pattern '=' python_exp
                     | pattern 'in' python_exp
                     | 'check' python_exp
                     | python_statements

Each of these clauses results in a Python expression being executed. Their meaning is as follows:

pattern '=' python_exp

  python_exp is evaluated and the result matched with pattern. If the result does not match, the clause fails.

  The clause always fails on backtracking, meaning that it only produces a single result (contrasted with `in`).

pattern 'in' python_exp

  python_exp is evaluated to produce a Python iterable and the first element from the resulting iterable is matched with pattern. On backtracking, successive elements from the iterable are matched with pattern. When the result is exhausted, the clause fails.

  This has the effect of offering each element of the result, one at a time, to the subsequent premise clauses. Each element is thus acted upon individually.

'check' python_exp
  python_exp is evaluated. If the result is Python "true" the clause succeeds, otherwise it fails. The clause always fails on backtracking.

## Python_statements

    python_statements ::= 'python' python_statement
                        | 'python' NL INDENT
                              {python_statement NL}
                          DEINDENT

This clause allows the inclusion of arbitrary Python statements in your rules. This premise always succeeds; and then fails on backtracking.

The current `knowledge_engine` object is available within python_statements as the variable called `engine`.

Caution!

Always keep in mind the difference between pattern variables and Python variables. Pattern variables are always indicated with a `$` and are only bound to a value during inferencing.

1. Thus, a `python_statement` may not set a pattern variable. Storing a value computed by Python into a pattern variable can only be done using the python_premise:

       <pattern> = <some python expression>

2. When a pattern variable is used within a Python expression or statement, it must be fully bound.

3. Python variables are not visible to the inference engine. They are local variables that are also not visible to Python code in other rules or other invocations of the same rule.

4. Finally, Python variables in the when clause of a backward-chaining rule are not visible to the Python code in the with clause of the same rule. (These end up in two different Python functions after the .krb file is compiled). So this won't work:

       some_bc_rule
           use some_goal(...)
           when
               ...
               python x_list = <some python expression>
               ...
           with
               for x in x_list: process(x)

   In this case, assign the value of the Python variable to a pattern variable in the when clause and then use that pattern variable in the with clause:

       some_bc_rule
           use some_goal(...)
           when
               ...
               python x_list = <some python expression>
               ...
               $x_list = tuple(x_list)
           with
               for x in $x_list: process(x)

Copyright © 2007-2009 Bruce Frederiksen

Page last modified Sun, Feb 15 2009.