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.
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>
When a pattern variable is used within a Python expression or statement, it must be fully bound.
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.
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)