Python–term conversions¶
Logic programs manipulate terms (see Terms and variables);
Python programs manipulate Python values. 2PPy converts between the two with
tuprolog.core.to_term and tuprolog.core.to_python,
and applies them automatically at most places where the two worlds meet.
From Python to terms: to_term¶
| Python value | Term | Example |
|---|---|---|
| a term | the term itself | to_term(atom("a")) is a |
str |
atom | "bart" → bart, "Hello World" → 'Hello World' |
bool |
truth | True → true, False → false |
int (any size) |
integer | 42 → 42, 10**30 → 1000000000000000000000000000000 |
float |
real, from the float's shortest representation | 0.1 → 0.1 |
decimal.Decimal |
real, without trailing zeros | Decimal("1.50") → 1.5 |
list |
logic list, items converted | [1, "a"] → [1, a] |
tuple of 2+ items |
logic tuple (conjunction), items converted | (1, "a") → (1, a) |
| 1-tuple | its item, converted | ("a",) → a |
Anything else (None, dicts, sets, the empty tuple, arbitrary objects) raises TypeError.
Note that strings always become atoms: to get a variable, create one with var("X") (or parse
text with tuprolog.core.parsing.parse_term).
>>> from decimal import Decimal
>>> from tuprolog.core import atom, to_term
>>> to_term("bart"), to_term("Hello World"), to_term(True), to_term(42), to_term(0.1)
(bart, 'Hello World', true, 42, 0.1)
>>> to_term(Decimal("1.50")), to_term(10**30)
(1.5, 1000000000000000000000000000000)
>>> to_term([1, "a", (2, 3)]), to_term(("a",))
([1, a, (2, 3)], a)
>>> to_term(None)
Traceback (most recent call last):
...
TypeError: Cannot convert NoneType into a term: None
From terms to Python: to_python¶
| Term | Python value | Example |
|---|---|---|
truth (true, false, fail) |
bool |
true → True, fail → False |
| integer | int |
42 → 42 |
| real | float (possibly losing precision) |
2.5 → 2.5 |
well-formed list (incl. []) |
list, items converted |
[1, a] → [1, 'a'], [] → [] |
| tuple | tuple, items converted |
(1, a) → (1, 'a') |
| other atom | str |
bart → 'bart' |
anything else (variables, compound terms, partial lists like [1 \| T]) |
the term itself | f(a) → f(a) |
>>> from tuprolog.core import to_python
>>> from tuprolog.core.parsing import parse_term
>>> to_python(parse_term("[1, 2.5, a, true, (b, c)]"))
[1, 2.5, 'a', True, ('b', 'c')]
>>> to_python(parse_term("fail")), to_python(parse_term("[]"))
(False, [])
>>> to_python(parse_term("f(a)")), to_python(parse_term("[1 | T]"))
(f(a), [1 | T_...])
to_python(to_term(v)) == v holds for strings, booleans, ints, lists and tuples of them; floats
round-trip through their shortest representation, and Decimals become floats.
Where conversions happen automatically¶
| Where | Direction | What is converted |
|---|---|---|
Term factories struct, logic_list, logic_list_from, logic_tuple (tuprolog.core) |
Python → term | their arguments/items, e.g. struct("f", "a", 1) is f(a, 1) |
Substitutions substitution, unifier (tuprolog.core), and Struct.set_args, Struct.insert_at |
Python → term | the assigned values, and the new arguments, e.g. substitution({X: 1}) |
Flags: flag, flag_store, store + {...} (tuprolog.solve.flags) |
Python → term | flag values, e.g. flag_store(unknown="fail") |
Solver.query and Solution.to_dict (tuprolog.solve) |
term → Python | the bindings of the query's variables, e.g. {'X': 1} |
predicate (tuprolog.solve.primitive) |
both | the goal's arguments are passed through to_python; returned tuples of values are converted by to_term and unified with the arguments |
function (tuprolog.solve.function) |
both | the evaluated arguments through to_python, the result through to_term |
| OOPLib | both | call arguments through to_python (references and $aliases stand for their objects, Key = Value gives keyword arguments); numbers, booleans and strings returned by Python become terms, other objects references (atoms like '<object:list#...>') |
>>> from tuprolog.core import struct
>>> from tuprolog.solve.prolog import prolog_solver
>>> struct("point", 1, 2.5, "origin")
point(1, 2.5, origin)
>>> list(prolog_solver().query("X = [1, a], Y = f(b), Z = (c, d)"))
[{'X': [1, 'a'], 'Y': f(b), 'Z': ('c', 'd')}]
Solution.bindings (and solution[name]) give the bound terms instead, unconverted.
Other factories take terms (or plain Python values only where documented, e.g. atom takes a
string, integer an int): check their docstrings in the API reference.
Methods of JVM objects that have no Pythonic counterpart take and return JVM values: JPype
converts Python str, int, float and bool to their JVM counterparts, and may return
java.lang.Strings where 2P-Kt returns strings (use str(...) to get Python strings).