Python objects from Prolog¶
OOPLib lets Prolog code create Python objects, call their methods and read their attributes.
Objects are referred to by atoms (references such as '<object:list#...>') and aliases such as
$math; X := Receiver.method(Args) calls a method and binds its result.
See also: Use Python objects from Prolog, OOPLib reference.
In [1]:
Copied!
from tuprolog.solve.libs import OOPLib
from tuprolog.solve.prolog import prolog_solver
solver = prolog_solver(libraries=OOPLib)
list(solver.query("X := $math.sqrt(2), Y := $math.floor(X)"))
from tuprolog.solve.libs import OOPLib
from tuprolog.solve.prolog import prolog_solver
solver = prolog_solver(libraries=OOPLib)
list(solver.query("X := $math.sqrt(2), Y := $math.floor(X)"))
Out[1]:
[{'X': 1.4142135623730951, 'Y': 1}]
Objects are created with new_object/3, and stay referenced across goals of the same query:
In [2]:
Copied!
list(
solver.query("new_object($list, [], L), L.append(c), L.append(a), L.sort, list_items(L, Items)")
)
list(
solver.query("new_object($list, [], L), L.append(c), L.append(a), L.sort, list_items(L, Items)")
)
Out[2]:
[{'L': '<object:list#7f0587d60240>', 'Items': ['a', 'c']}]
Keyword arguments are written Key = Value; as converts values by calling types:
In [3]:
Copied!
list(solver.query("J := $json.dumps([1, 2, 3], separators = [',', ':']), N := '42' as $int"))
list(solver.query("J := $json.dumps([1, 2, 3], separators = [',', ':']), N := '42' as $int"))
Out[3]:
[{'J': '[1,2,3]', 'N': 42}]
Custom aliases and safety¶
By default, only side-effect free standard modules are reachable, and private attributes are not.
oop_lib builds a library with other limits, or with aliases for your own classes:
In [4]:
Copied!
from dataclasses import dataclass
from tuprolog.solve.libs import oop_lib
@dataclass
class Point:
x: float
y: float
def norm(self):
return (self.x**2 + self.y**2) ** 0.5
solver = prolog_solver(libraries=oop_lib(aliases={"point": Point}))
list(solver.query("new_object($point, [3, 4], P), N := P.norm, X := P.x"))
from dataclasses import dataclass
from tuprolog.solve.libs import oop_lib
@dataclass
class Point:
x: float
y: float
def norm(self):
return (self.x**2 + self.y**2) ** 0.5
solver = prolog_solver(libraries=oop_lib(aliases={"point": Point}))
list(solver.query("new_object($point, [3, 4], P), N := P.norm, X := P.x"))
Out[4]:
[{'P': '<object:Point#7f0587d5e1b0>', 'N': 5.0, 'X': 3}]